├── .gitignore ├── .gitmodules ├── AUTHORS ├── CMakeLists.txt ├── INSTALLATION ├── LICENSE ├── README ├── build.sh ├── clayparser.cpp ├── clayparser.h ├── clintbeta.cpp ├── clintbeta.h ├── clintdependence.cpp ├── clintdependence.h ├── clintinterface.cpp ├── clintinterface.h ├── clintprogram.cpp ├── clintprogram.h ├── clintprojectionoverview.cpp ├── clintprojectionoverview.h ├── clintscop.cpp ├── clintscop.h ├── clintstmt.cpp ├── clintstmt.h ├── clintstmtoccurrence.cpp ├── clintstmtoccurrence.h ├── clintwindow.cpp ├── clintwindow.h ├── cmake-uninstall.cmake.in ├── dependenceanalyzer.cpp ├── dependenceanalyzer.h ├── enumerator.cpp ├── enumerator.h ├── examples ├── diagonal.c ├── diagonal.scop ├── localdim.c ├── localdim.scop ├── localdimsched.c ├── localdimsched.scop ├── maxviz.c ├── maxviz.scop ├── next.c ├── next.scop ├── onedim.c ├── onedim.scop ├── oneiter.c ├── oneiter.scop ├── simple.c ├── simple.scop ├── statement.c ├── statement.scop ├── triangles.c ├── triangles.scop ├── unions.c ├── unions.scop ├── visu.c └── visu.scop ├── macros.h ├── main.cpp ├── oslutils.cpp ├── oslutils.h ├── projectionview.cpp ├── projectionview.h ├── propertiesdialog.cpp ├── propertiesdialog.h ├── redocmake.sh ├── transformation.cpp ├── transformation.h ├── transformer.cpp ├── transformer.h ├── uninstall.sh ├── vizcoordinatesystem.cpp ├── vizcoordinatesystem.h ├── vizdeparrow.cpp ├── vizdeparrow.h ├── vizhandle.cpp ├── vizhandle.h ├── vizmanipulationmanager.cpp ├── vizmanipulationmanager.h ├── vizpoint.cpp ├── vizpoint.h ├── vizpolyhedron.cpp ├── vizpolyhedron.h ├── vizprojection.cpp ├── vizprojection.h ├── vizproperties.cpp ├── vizproperties.h ├── vizselectionmanager.cpp └── vizselectionmanager.h /.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | moc_* 3 | Makefile 4 | build/* 5 | release/* 6 | *.user* 7 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "openscop"] 2 | path = openscop 3 | url = https://github.com/ftynse/openscop 4 | [submodule "clan"] 5 | path = clan 6 | url = https://github.com/ftynse/clan 7 | [submodule "cloog"] 8 | path = cloog 9 | url = https://github.com/ftynse/cloog 10 | [submodule "candl"] 11 | path = candl 12 | url = https://github.com/ftynse/candl 13 | [submodule "clay"] 14 | path = clay 15 | url = https://github.com/ftynse/clay 16 | [submodule "chlore"] 17 | path = chlore 18 | url = https://github.com/ftynse/chlore 19 | [submodule "isl"] 20 | path = isl 21 | url = http://repo.or.cz/isl.git 22 | [submodule "piplib"] 23 | path = piplib 24 | url = https://github.com/periscop/piplib 25 | -------------------------------------------------------------------------------- /AUTHORS: -------------------------------------------------------------------------------- 1 | Oleksandr Zinenko 2 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | project(clint) 2 | cmake_minimum_required(VERSION 3.0) 3 | set(CMAKE_CXX_STANDARD 14) 4 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 5 | set(CMAKE_CXX_FLAGS "-Wall -pedantic -O3 -Wno-sign-compare") 6 | set(CMAKE_CXX_FLAGS_DEBUG "-Wall -pedantic -O0 -g") 7 | 8 | if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") 9 | message(STATUS "Using clang compiler") 10 | #set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -Wdocumentation") # Boost doxygen generates too many errors. 11 | elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") 12 | message(STATUS "Using GNU compiler") 13 | set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -Wextra") 14 | else() 15 | message(STATUS "Using ${CMAKE_CXX_COMPILER_ID} compiler. No predefined flags set") 16 | endif() 17 | 18 | # Periscop projects 19 | find_package(osl REQUIRED) 20 | if(NOT DEFINED OSL_FOUND) 21 | message(FATAL_ERROR "osl library not found") 22 | else() 23 | message(STATUS "Using osl library from: ${OSL_LIBRARY}") 24 | endif() 25 | 26 | find_package(cloog-isl REQUIRED) 27 | if(NOT DEFINED CLOOG_ISL_FOUND) 28 | message(FATAL_ERROR "cloog-isl library not found") 29 | else() 30 | message(STATUS "Using osl library from: ${CLOOG_ISL_LIBRARY}") 31 | endif() 32 | 33 | find_package(candl REQUIRED) 34 | if(NOT DEFINED CANDL_FOUND) 35 | message(FATAL_ERROR "candl library not found") 36 | else() 37 | message(STATUS "Using candl library form: ${CANDL_LIBRARY}") 38 | endif() 39 | 40 | find_package(clan REQUIRED) 41 | if(NOT DEFINED CLAN_FOUND) 42 | message(FATAL_ERROR "clan library not found") 43 | else() 44 | message(STATUS "Using clan library from: ${CLAN_LIBRARY}") 45 | endif() 46 | 47 | find_package(clay REQUIRED) 48 | if(NOT DEFINED CLAY_FOUND) 49 | message(FATAL_ERROR "clay library not found") 50 | else() 51 | message(STATUS "Using clay library from: ${CLAY_LIBRARY}") 52 | endif() 53 | 54 | find_package(piplibmp REQUIRED) 55 | if(NOT DEFINED PIPLIBMP_FOUND) 56 | message(FATAL_ERROR "piplib_MP not found") 57 | else() 58 | message(STATUS "Using piplib library with multiprecision from: ${PIPLIBMP_LIBRARY}") 59 | endif() 60 | 61 | find_package(chlore REQUIRED) 62 | if(NOT DEFINED CHLORE_FOUND) 63 | message(FATAL_ERROR "chlore library not found") 64 | else() 65 | message(STATUS "Using chlore library from: ${CHLORE_LIBRARY}") 66 | endif() 67 | 68 | find_library(GMP_LIBRARY gmp) 69 | find_path(GMP_INCLUDE_DIR gmp.h) 70 | 71 | find_library(ISL_LIBRARY isl) 72 | find_path(ISL_INCLUDE_DIR isl/ctx.h) 73 | 74 | if(ISL_INCLUDE_DIR) 75 | message(STATUS "Using isl library from: ${ISL_LIBRARY}") 76 | else() 77 | message(FATAL_ERROR "isl library not found") 78 | endif() 79 | 80 | include_directories(${OSL_INCLUDE_DIR}) 81 | include_directories(${CLOOG_ISL_INCLUDE_DIR}) 82 | include_directories(${CANDL_INCLUDE_DIR}) 83 | include_directories(${CLAN_INCLUDE_DIR}) 84 | include_directories(${CLAY_INCLUDE_DIR}) 85 | include_directories(${GMP_INCLUDE_DIR}) 86 | include_directories(${ISL_INCLUDE_DIR}) 87 | include_directories(${PIPLIBMP_INCLUDE_DIR}) 88 | include_directories(${CHLORE_INCLUDE_DIR}) 89 | 90 | # Qt libraries 91 | set(CMAKE_INCLUDE_CURRENT_DIR ON) 92 | set(CMAKE_AUTOMOC ON) 93 | 94 | find_package(Qt5Core REQUIRED) 95 | find_package(Qt5Gui REQUIRED) 96 | find_package(Qt5Widgets REQUIRED) 97 | include_directories(${Qt5Core_INCLUDE_DIRS}) 98 | 99 | aux_source_directory(. SRC_LIST) 100 | add_executable(${PROJECT_NAME} ${SRC_LIST} macros.h) 101 | 102 | qt5_use_modules(${PROJECT_NAME} Widgets Gui Core Xml Svg) 103 | 104 | # Boost libraries 105 | set(Boost_USE_STATIC_LIBS OFF) 106 | set(Boost_USE_STATIC_RUNTIME OFF) 107 | find_package(Boost 1.55.0 REQUIRED) 108 | 109 | if(Boost_FOUND) 110 | include_directories(${Boost_INCLUDE_DIRS}) 111 | target_link_libraries(${PROJECT_NAME} ${Boost_LIBRARIES}) 112 | else() 113 | message(FATAL_ERROR "boost library not found") 114 | endif() 115 | 116 | target_link_libraries(${PROJECT_NAME} ${OSL_LIBRARY}) 117 | target_link_libraries(${PROJECT_NAME} ${ISL_LIBRARY}) 118 | target_link_libraries(${PROJECT_NAME} ${CLOOG_ISL_LIBRARY}) 119 | target_link_libraries(${PROJECT_NAME} ${CLAN_LIBRARY}) 120 | target_link_libraries(${PROJECT_NAME} ${CANDL_LIBRARY}) 121 | target_link_libraries(${PROJECT_NAME} ${CLAY_LIBRARY}) 122 | target_link_libraries(${PROJECT_NAME} ${PIPLIBMP_LIBRARY}) 123 | target_link_libraries(${PROJECT_NAME} ${CHLORE_LIBRARY}) 124 | 125 | install(TARGETS ${PROJECT_NAME} RUNTIME DESTINATION bin) 126 | 127 | configure_file( 128 | "${CMAKE_CURRENT_SOURCE_DIR}/cmake-uninstall.cmake.in" 129 | "${CMAKE_CURRENT_BINARY_DIR}/cmake-uninstall.cmake" 130 | IMMEDIATE @ONLY) 131 | 132 | add_custom_target(uninstall 133 | COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake-uninstall.cmake) 134 | -------------------------------------------------------------------------------- /INSTALLATION: -------------------------------------------------------------------------------- 1 | Prerequisites 2 | ------------- 3 | 4 | Clint should build on most modern POSIX and BSD systems with windowing 5 | interfaces. It requires the following widely available libraries to be 6 | installed and visible in respective pathes: 7 | * Qt (version 5.4 or later) 8 | * Boost (version 1.55 or later) 9 | * GMP (version 6.0 or later) 10 | These libraries should be available in all major distributions and were tested 11 | in Debian stable (Jessie). 12 | 13 | The build process is multi-stage and requies the following tools: 14 | * make 15 | * autotools 16 | * autoconf 17 | * libtool 18 | * cmake (version 3.0 or later) 19 | * flex 20 | * bison 21 | Clint must be compiled with C++14 support (clang-3.5+ or GCC 4.9+ required). 22 | 23 | It also requires *development* versions of the following polyhedral framework 24 | libraries: 25 | * isl 26 | * OpenScop 27 | * CLooG 28 | * Clan 29 | * Candl 30 | * Clay 31 | * Chlore 32 | all of which are available via git submodules mechanism. Do *not* initialize 33 | submodules if you intend to use the Clint build script. Do *not* recursively 34 | initalize submodules at all as they rely on each other. Please note that older 35 | versions of these libraries may be already installed in your distribution as a 36 | part of production compiler, e.g. GCC or Clang. These versions may not be 37 | compatible with Clint. 38 | 39 | Building and installing 40 | ----------------------- 41 | 42 | Clint is provided with a script that builds and installs the projet and the 43 | polyhedral libraries and tools. Run 44 | ./build.sh 45 | to execute it. This script will initalize and download submodules, build and 46 | install them before building and installing Clint. After installation, clint 47 | executable file will be available in the installation directory. 48 | 49 | Build script is parameterized by the following environment variables: 50 | PREFIX -- installation path [default=$HOME/usr] 51 | QTPREFIX -- path where Qt is installed [default=/usr/lib] 52 | JOBS -- number of parallel `make' jobs [default=8]. 53 | 54 | Tools and libraries are automatically installed to: 55 | $PREFIX/bin -- executables 56 | $PREFIX/lib -- libraries 57 | $PREFIX/include -- header files for the development. 58 | For example, clint executable will be available at $PREFIX/bin/clint. 59 | Ensure that the dynamic linker will be able to find the newly installed 60 | libraries by, e.g., changing (DY)LD_LIBRARY_PATH. 61 | 62 | Building Clint for Windows was never tested, however it does not depend on 63 | non-standard or platform-dependent behavior and should work as long as the 64 | library dependences are satisfied. 65 | 66 | Uninstalling 67 | ------------ 68 | 69 | Clint is provided with an uninstallation script. Run 70 | ./uninstall.sh 71 | to execute it. Please note that this script uses the files that were created 72 | during the build process and is not guaranteed to completely remove Clint and 73 | all libraries if it is not called from the same location as the build script, 74 | especially for a different version. 75 | 76 | If you installed Clint to a specific folder identified by PREFIX, removing this 77 | folder suffices to completely delete Clint. 78 | 79 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2013-2016, Inria. 2 | All rights reserved. 3 | Written by Oleksandr Zinenko 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright 10 | notice, this list of conditions and the following disclaimer in the 11 | documentation and/or other materials provided with the distribution. 12 | * Neither the name of the nor the 13 | names of its contributors may be used to endorse or promote products 14 | derived from this software without specific prior written permission. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY 20 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | Chunky Loop INTerface (clint): a visual interface for representing and 2 | interacting with the loop-based programs in the 3 | polyhedral model. 4 | 5 | This software is a research prototype and is not intended for the production 6 | use. It is known to be incomplet and inkorrect. 7 | 8 | Please contact the author directly should you have any questions. 9 | 10 | Written by Oleksandr Zinenko 11 | 12 | (c) 2014, Inria. 13 | 14 | -------------------------------------------------------------------------------- /build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -x 3 | set -e 4 | 5 | git submodule deinit -f . 6 | git submodule init 7 | git submodule update 8 | 9 | if [ -z ${PREFIX+x} ]; then 10 | PREFIX=$HOME/usr 11 | fi; 12 | 13 | if [ -z ${QTPREFIX+x} ]; then 14 | QTPREFIX=/usr/lib 15 | fi; 16 | 17 | if [ -z ${JOBS+x} ]; then 18 | JOBS=8 19 | fi; 20 | 21 | cd isl 22 | ./autogen.sh 23 | ./configure --prefix=$PREFIX 24 | make -j $JOBS && make install 25 | cd - 26 | 27 | cd openscop 28 | ./autogen.sh 29 | ./configure --prefix=$PREFIX 30 | make -j $JOBS && make install 31 | cd - 32 | 33 | cd cloog 34 | ./autogen.sh 35 | ./configure --with-osl-builddir=../openscop \ 36 | --with-isl-builddir=../isl \ 37 | --prefix=$PREFIX 38 | make -j $JOBS && make install 39 | cd - 40 | 41 | cd clan 42 | ./autogen.sh 43 | ./configure --with-osl-builddir=../openscop \ 44 | --prefix=$PREFIX 45 | make -j $JOBS && make install 46 | cd - 47 | 48 | cd piplib 49 | ./autogen.sh 50 | ./configure --with-gmp \ 51 | --prefix=$PREFIX 52 | make -j $JOBS && make install 53 | cd - 54 | 55 | cd candl 56 | ./autogen.sh 57 | ./configure --with-osl-builddir=../openscop \ 58 | --with-piplib-builddir=../piplib \ 59 | --prefix=$PREFIX 60 | make -j $JOBS && make install 61 | cd - 62 | 63 | cd clay 64 | ./autogen.sh 65 | ./configure --with-osl-builddir=../openscop \ 66 | --with-cloog-builddir=../cloog \ 67 | --with-clan-builddir=../clan \ 68 | --prefix=$PREFIX 69 | make -j $JOBS && make install 70 | cd - 71 | 72 | mkdir chlore/build 73 | cd chlore/build 74 | cmake .. -DCMAKE_PREFIX_PATH=$PREFIX -DCMAKE_INSTALL_PREFIX=$PREFIX 75 | make -j $JOBS && make install 76 | cd - 77 | 78 | mkdir build 79 | cd build 80 | cmake .. -DCMAKE_PREFIX_PATH=$PREFIX\;$QTPREFIX -DCMAKE_INSTALL_PREFIX=$PREFIX -DCMAKE_BUILD_TYPE=Release 81 | make -j $JOBS && make install 82 | cd - 83 | 84 | -------------------------------------------------------------------------------- /clayparser.cpp: -------------------------------------------------------------------------------- 1 | #include "clayparser.h" 2 | #include "transformation.h" 3 | 4 | #include 5 | #include 6 | 7 | #include 8 | 9 | #include 10 | #include 11 | 12 | #include 13 | #include 14 | 15 | #include 16 | 17 | #include 18 | 19 | #include 20 | #include 21 | #include 22 | 23 | #include 24 | #include 25 | #include 26 | 27 | namespace { 28 | 29 | class string_builder { 30 | public: 31 | template 32 | std::string operator () (Args... args){ 33 | std::stringstream stream; 34 | build(stream, args...); 35 | return std::move(stream.str()); 36 | } 37 | 38 | private: 39 | template 40 | std::enable_if_t 41 | build (std::stringstream &stream, Arg arg, Args... args) { 42 | stream << arg; 43 | build(stream, args...); 44 | } 45 | 46 | template 47 | void build (std::stringstream &stream, Arg arg) { 48 | stream << arg; 49 | } 50 | }; 51 | 52 | namespace clay_parser { 53 | namespace fusion = boost::fusion; 54 | namespace phoenix = boost::phoenix; 55 | namespace qi = boost::spirit::qi; 56 | namespace ascii = boost::spirit::ascii; 57 | 58 | struct clay_parser_list { 59 | std::vector first; 60 | std::vector second; 61 | std::vector third; 62 | std::vector fourth; 63 | }; 64 | 65 | typedef boost::variant, int, clay_parser_list> clay_parser_arg; 66 | 67 | struct clay_parser_command { 68 | std::string name; 69 | std::vector arguments; 70 | }; 71 | 72 | } // end namespace clay_parser 73 | 74 | } // end anonymous namespace 75 | 76 | BOOST_FUSION_ADAPT_STRUCT( 77 | clay_parser::clay_parser_list, 78 | (std::vector, first) 79 | (std::vector, second) 80 | (std::vector, third) 81 | (std::vector, fourth) 82 | ) 83 | 84 | BOOST_FUSION_ADAPT_STRUCT( 85 | clay_parser::clay_parser_command, 86 | (std::string, name) 87 | (std::vector, arguments) 88 | ) 89 | 90 | namespace { 91 | 92 | namespace clay_parser { 93 | 94 | template 95 | struct clay_grammar : qi::grammar(), ascii::space_type> { 96 | clay_grammar() : clay_grammar::base_type(start) { 97 | using qi::lexeme; 98 | using qi::int_; 99 | using ascii::char_; 100 | using ascii::string; 101 | using namespace qi::labels; 102 | 103 | using phoenix::at_c; 104 | using phoenix::push_back; 105 | text = lexeme[+(char_ - '(') [_val += _1]]; 106 | 107 | int_list = int_ % ','; 108 | 109 | beta_empty = (lexeme["["] >> ']') [_val = std::vector()]; 110 | 111 | beta_full = '[' 112 | >> int_list [_val = _1] 113 | >> ']'; 114 | 115 | beta = (beta_full | beta_empty) [_val = _1]; 116 | 117 | constant = int_; 118 | 119 | list = '{' 120 | >> -int_list [at_c<3>(_val) = _1] 121 | >> -lexeme["|"] [at_c<2>(_val) = at_c<3>(_val), at_c<3>(_val) = std::vector()] 122 | >> -int_list [at_c<3>(_val) = _1] 123 | >> -lexeme["|"] [at_c<1>(_val) = at_c<2>(_val), at_c<2>(_val) = at_c<3>(_val), at_c<3>(_val) = std::vector()] 124 | >> -int_list [at_c<3>(_val) = _1] 125 | >> -lexeme["|"] [at_c<0>(_val) = at_c<1>(_val), at_c<1>(_val) = at_c<2>(_val), at_c<2>(_val) = at_c<3>(_val), at_c<3>(_val) = std::vector()] 126 | >> -int_list [at_c<3>(_val) = _1] 127 | >> '}'; 128 | 129 | arg = (beta | constant | list) [_val = _1]; 130 | 131 | arg_list = arg % ','; 132 | 133 | command = text [at_c<0>(_val) = _1] 134 | >> '(' 135 | >> arg_list [at_c<1>(_val) = _1] 136 | >> ')'; 137 | 138 | sequence = command % ';'; 139 | 140 | start = sequence [_val = _1] 141 | >> ';'; 142 | } 143 | 144 | qi::rule(), ascii::space_type> start; 145 | qi::rule(), ascii::space_type> sequence; 146 | qi::rule command; 147 | qi::rule(), ascii::space_type> arg_list; 148 | qi::rule arg; 149 | qi::rule list; 150 | qi::rule constant; 151 | qi::rule(), ascii::space_type> beta_full; 152 | qi::rule(), ascii::space_type> beta_empty; 153 | qi::rule(), ascii::space_type> beta; 154 | qi::rule(), ascii::space_type> int_list; 155 | qi::rule text; 156 | }; 157 | 158 | class syntax_error : public std::logic_error { 159 | using std::logic_error::logic_error; 160 | }; 161 | 162 | class semantic_error : public std::logic_error { 163 | using std::logic_error::logic_error; 164 | }; 165 | } 166 | 167 | enum clay_parser_arg_kind : size_t { 168 | vector, 169 | constant, 170 | list 171 | }; 172 | 173 | #define szck_block(n) \ 174 | if (cmd.arguments.size() != n) \ 175 | throw clay_parser::semantic_error( \ 176 | string_builder()(cmd.arguments.size() < n ? "Not enough" : "Too many", \ 177 | " arguments for [", cmd.name, "], expecting ", n, " got ", cmd.arguments.size())); \ 178 | 179 | 180 | #define uwrp_block(n) \ 181 | boost::optional arg##n##_optional; \ 182 | try { arg##n##_optional = boost::get(cmd.arguments[(n - 1)]); } \ 183 | catch (boost::bad_get) { \ 184 | throw clay_parser::semantic_error(string_builder()("Argument ", n, " has incorrect type. Expected ", typeid(T##n).name())); }\ 185 | T##n arg##n = arg##n##_optional.get(); 186 | 187 | template 188 | std::function 189 | unwrap(std::function f) { 190 | return [f] (const clay_parser::clay_parser_command &cmd) { 191 | szck_block(1); 192 | uwrp_block(1); 193 | return f(arg1); 194 | }; 195 | } 196 | 197 | template 198 | std::function 199 | unwrap(std::function f) { 200 | return [f] (const clay_parser::clay_parser_command &cmd) { 201 | szck_block(2); 202 | uwrp_block(1); 203 | uwrp_block(2); 204 | return f(arg1, arg2); 205 | }; 206 | } 207 | 208 | template 209 | std::function 210 | unwrap(std::function f) { 211 | return [f] (const clay_parser::clay_parser_command &cmd) { 212 | szck_block(3); 213 | uwrp_block(1); 214 | uwrp_block(2); 215 | uwrp_block(3); 216 | return f(arg1, arg2, arg3); 217 | }; 218 | } 219 | 220 | template 221 | std::function 222 | unwrap(std::function f) { 223 | return [f] (const clay_parser::clay_parser_command &cmd) { 224 | szck_block(4); 225 | uwrp_block(1); 226 | uwrp_block(2); 227 | uwrp_block(3); 228 | uwrp_block(4); 229 | return f(arg1, arg2, arg3, arg4); 230 | }; 231 | } 232 | 233 | template 234 | std::function 235 | unwrap(std::function f) { 236 | return [f] (const clay_parser::clay_parser_command &cmd) { 237 | szck_block(5); 238 | uwrp_block(1); 239 | uwrp_block(2); 240 | uwrp_block(3); 241 | uwrp_block(4); 242 | uwrp_block(5); 243 | return f(arg1, arg2, arg3, arg4, arg5); 244 | }; 245 | } 246 | 247 | #undef uwrp_block 248 | 249 | Transformation create_transformation(const clay_parser::clay_parser_command &cmd, 250 | const std::unordered_map> &mapping) { 251 | auto iterator = mapping.find(cmd.name); 252 | if (iterator == std::end(mapping)) 253 | throw clay_parser::semantic_error(string_builder()("Transformation [", cmd.name, "] not found.")); 254 | 255 | std::function descriptor = iterator->second; 256 | 257 | return descriptor(cmd); 258 | } 259 | 260 | static std::vector> wrapClayParserList(const clay_parser::clay_parser_list &&list) { 261 | std::vector> wrapped(4); 262 | wrapped[0] = list.first; 263 | wrapped[1] = list.second; 264 | wrapped[2] = list.third; 265 | wrapped[3] = list.fourth; 266 | return std::move(wrapped); 267 | } 268 | 269 | Transformation wrappedIss(const std::vector &beta, const clay_parser::clay_parser_list &&list) { 270 | return Transformation::rawIss(beta, wrapClayParserList(std::forward(list))); 271 | } 272 | 273 | TransformationGroup create_group(const std::vector &commands) { 274 | TransformationGroup group; 275 | 276 | std::unordered_map> mapping; 277 | mapping["split"] = unwrap, int> (Transformation::rawSplit); 278 | mapping["fission"] = mapping["split"]; 279 | mapping["distribute"] = mapping["split"]; 280 | mapping["fuse"] = unwrap> (Transformation::fuseNext); 281 | mapping["reorder"] = unwrap, std::vector> (Transformation::rawReorder); 282 | mapping["shift"] = unwrap, int, std::vector, int> (Transformation::rawShift); 283 | mapping["skew"] = unwrap, int, int, int> (Transformation::skew); 284 | mapping["grain"] = unwrap, int, int> (Transformation::grain); 285 | mapping["interchange"] = unwrap, int, int> (Transformation::interchange); 286 | mapping["reverse"] = unwrap, int> (Transformation::reverse); 287 | mapping["tile"] = unwrap, int, int, int, int> (Transformation::rawTile); 288 | mapping["iss"] = unwrap, clay_parser::clay_parser_list> (wrappedIss); 289 | mapping["reshape"] = unwrap, int, int, int> (Transformation::reshape); 290 | mapping["linearize"] = unwrap, int> (Transformation::linearize); 291 | mapping["collapse"] = unwrap> (Transformation::collapse); 292 | mapping["embed"] = unwrap> (Transformation::embed); 293 | mapping["unembed"] = unwrap> (Transformation::unembed); 294 | mapping["densify"] = unwrap, int> (Transformation::densify); 295 | 296 | 297 | for (const clay_parser::clay_parser_command &cmd : commands) { 298 | group.transformations.push_back(create_transformation(cmd, mapping)); 299 | } 300 | return std::move(group); 301 | } 302 | 303 | void print_parser_command(std::vector parser_command_list) { 304 | for (const clay_parser::clay_parser_command &cmd : parser_command_list) { 305 | std::cout << cmd.name << " "; 306 | for (const clay_parser::clay_parser_arg &arg : cmd.arguments) { 307 | if (const int *constant = boost::get(&arg)) { 308 | std::cout << *constant << " "; 309 | } else if (const std::vector *beta = boost::get>(&arg)) { 310 | std::cout << "["; 311 | std::copy(beta->cbegin(), beta->cend(), std::ostream_iterator(std::cout, ",")); 312 | std::cout << "] "; 313 | } else if (const clay_parser::clay_parser_list *list = boost::get(&arg)) { 314 | std::cout << "{"; 315 | std::copy(list->first.cbegin(), list->first.cend(), std::ostream_iterator(std::cout, ",")); 316 | std::cout << "|"; 317 | std::copy(list->second.cbegin(), list->second.cend(), std::ostream_iterator(std::cout, ",")); 318 | std::cout << "|"; 319 | std::copy(list->third.cbegin(), list->third.cend(), std::ostream_iterator(std::cout, ",")); 320 | std::cout << "|"; 321 | std::copy(list->fourth.cbegin(), list->fourth.cend(), std::ostream_iterator(std::cout, ",")); 322 | std::cout << "} "; 323 | } else { 324 | std::cout << "wtf"; 325 | } 326 | } 327 | std::cout << std::endl; 328 | } 329 | } 330 | 331 | 332 | } // end anonymous namespace 333 | 334 | ClayParser::ClayParser() { 335 | } 336 | 337 | TransformationSequence ClayParser::parse(const std::string &text) { 338 | clay_parser::clay_grammar grammar; 339 | 340 | std::list> groups; 341 | for (size_t i = 0, e = text.size(); i < e; ) { 342 | size_t p = text.find("\n\n", i); 343 | if (p == std::string::npos) 344 | p = e; 345 | groups.push_back(boost::iterator_range( 346 | text.begin() + i, 347 | text.begin() + p)); 348 | i = p; 349 | } 350 | 351 | TransformationSequence sequence; 352 | for (boost::iterator_range &r : groups) { 353 | std::vector parsed; 354 | std::string::const_iterator iter = r.begin(), 355 | end = r.end(); 356 | bool result = boost::spirit::qi::phrase_parse( 357 | iter, 358 | end, 359 | grammar, 360 | boost::spirit::ascii::space, 361 | parsed); 362 | if (result && iter == end) { 363 | sequence.groups.push_back(create_group(parsed)); 364 | } else { 365 | throw clay_parser::syntax_error("Input text is not a clay transformation sequence"); 366 | } 367 | } 368 | 369 | return std::move(sequence); 370 | } 371 | 372 | -------------------------------------------------------------------------------- /clayparser.h: -------------------------------------------------------------------------------- 1 | #ifndef CLAYPARSER_H 2 | #define CLAYPARSER_H 3 | 4 | #include "transformation.h" 5 | #include 6 | 7 | class ClayParser { 8 | public: 9 | ClayParser(); 10 | TransformationSequence parse(const std::string &); 11 | }; 12 | 13 | #endif // CLAYPARSER_H 14 | -------------------------------------------------------------------------------- /clintbeta.cpp: -------------------------------------------------------------------------------- 1 | #include "clintbeta.h" 2 | 3 | #include 4 | #include 5 | 6 | ClintBeta::ClintBeta(const std::vector &beta) { 7 | m_beta.reserve(beta.size()); 8 | std::copy(std::begin(beta), std::end(beta), std::back_inserter(m_beta)); 9 | } 10 | 11 | ClintBeta::operator std::vector() { 12 | return m_beta; // new copy constructed 13 | } 14 | -------------------------------------------------------------------------------- /clintbeta.h: -------------------------------------------------------------------------------- 1 | #ifndef CLINTBETA_H 2 | #define CLINTBETA_H 3 | 4 | #include 5 | 6 | #include 7 | 8 | #include "macros.h" 9 | 10 | // TODO: pass Clint* to use of ClintBeta instead of std::vector 11 | class ClintBeta { 12 | public: 13 | ClintBeta() = default; 14 | ClintBeta(const std::vector &beta); 15 | explicit operator std::vector (); 16 | 17 | int &operator[] (int index) { 18 | CLINT_ASSERT(index >= 0, "Beta element index must be positive"); 19 | CLINT_ASSERT(index < m_beta.size(), "Beta-vector index overflow"); 20 | return m_beta.at(index); 21 | } 22 | 23 | bool operator== (const ClintBeta &other) { 24 | return m_beta == other.m_beta; 25 | } 26 | 27 | bool operator< (const ClintBeta &other) { 28 | return m_beta < other.m_beta; 29 | } 30 | 31 | private: 32 | std::vector m_beta; 33 | }; 34 | 35 | Q_DECLARE_METATYPE(ClintBeta) 36 | 37 | #endif // CLINTBETA_H 38 | -------------------------------------------------------------------------------- /clintdependence.cpp: -------------------------------------------------------------------------------- 1 | #include "clintdependence.h" 2 | #include "clintstmtoccurrence.h" 3 | 4 | ClintDependence::ClintDependence(osl_dependence_p dependence, 5 | ClintStmtOccurrence *source, 6 | ClintStmtOccurrence *target, 7 | bool violated, 8 | QObject *parent) : 9 | QObject(parent), m_dependence(dependence), m_source(source), m_target(target), 10 | m_violated(violated) { 11 | CLINT_ASSERT(source, "Dependence source must not be empty"); 12 | CLINT_ASSERT(target, "Dependence source must not be empty"); 13 | CLINT_ASSERT(source->scop() == target->scop(), "Cross-scop dependences are not allowed"); 14 | } 15 | 16 | std::vector> 17 | ClintDependence::projectOn(int horizontalDimIdx, int verticalDimIdx) { 18 | // XXX: forward-incompatibility 19 | CLINT_ASSERT(m_dependence->domain->next == nullptr, 20 | "Union detected in dependence relation; probably Candl was updated. " 21 | "Changed required in Clint to ensure compatibility."); 22 | 23 | int nbSourceColumns = m_dependence->source_nb_output_dims_domain + 24 | m_dependence->source_nb_output_dims_access; 25 | std::vector visibleDimensions; 26 | 27 | for (int i = 0; i < m_dependence->source_nb_output_dims_domain; i++) { 28 | visibleDimensions.push_back(i); 29 | } 30 | for (int i = 0; i < m_dependence->target_nb_output_dims_domain; i++) { 31 | visibleDimensions.push_back(nbSourceColumns + i); 32 | } 33 | 34 | osl_relation_p domain = osl_relation_nclone(m_dependence->domain, 1); 35 | domain->nb_output_dims += domain->nb_input_dims; 36 | domain->nb_input_dims = 0; 37 | osl_relation_p ready = oslRelationWithContext(domain, m_source->scop()->fixedContext()); 38 | osl_relation_free(domain); 39 | std::vector> projection = 40 | m_source->program()->enumerator()->enumerate(ready, visibleDimensions); 41 | return projection; 42 | } 43 | 44 | -------------------------------------------------------------------------------- /clintdependence.h: -------------------------------------------------------------------------------- 1 | #ifndef CLINTDEPENDENCE_H 2 | #define CLINTDEPENDENCE_H 3 | 4 | #include 5 | #include "oslutils.h" 6 | 7 | class ClintStmtOccurrence; 8 | 9 | class ClintDependence : public QObject { 10 | Q_OBJECT 11 | public: 12 | explicit ClintDependence(osl_dependence_p dependence, ClintStmtOccurrence *source, 13 | ClintStmtOccurrence *target, bool violated, 14 | QObject *parent = nullptr); 15 | 16 | std::vector> projectOn(int horizontalDimIdx, int verticalDimIdx); 17 | 18 | int sourceDimensionality() const { 19 | return m_dependence->source_nb_output_dims_domain; 20 | } 21 | 22 | int targetDimensionality() const { 23 | return m_dependence->target_nb_output_dims_domain; 24 | } 25 | 26 | ClintStmtOccurrence *source() const { 27 | return m_source; 28 | } 29 | 30 | ClintStmtOccurrence *target() const { 31 | return m_target; 32 | } 33 | 34 | bool isViolated() const { 35 | return m_violated; 36 | } 37 | 38 | signals: 39 | 40 | public slots: 41 | 42 | private: 43 | osl_dependence_p m_dependence; 44 | 45 | ClintStmtOccurrence *m_source; 46 | ClintStmtOccurrence *m_target; 47 | 48 | bool m_violated; 49 | }; 50 | 51 | #endif // CLINTDEPENDENCE_H 52 | -------------------------------------------------------------------------------- /clintinterface.cpp: -------------------------------------------------------------------------------- 1 | #include "clintinterface.h" 2 | 3 | ClintInterface::ClintInterface(QWidget *parent) : 4 | QWidget(parent) 5 | { 6 | } 7 | -------------------------------------------------------------------------------- /clintinterface.h: -------------------------------------------------------------------------------- 1 | #ifndef CLINTINTERFACE_H 2 | #define CLINTINTERFACE_H 3 | 4 | #include 5 | #include 6 | 7 | #include "vizprojection.h" 8 | 9 | class ClintInterface : public QWidget 10 | { 11 | Q_OBJECT 12 | public: 13 | explicit ClintInterface(QWidget *parent = 0); 14 | 15 | signals: 16 | 17 | public slots: 18 | 19 | private: 20 | // Interface is a list of projections 21 | QList projections_; 22 | }; 23 | 24 | #endif // CLINTINTERFACE_H 25 | -------------------------------------------------------------------------------- /clintprogram.cpp: -------------------------------------------------------------------------------- 1 | #include "macros.h" 2 | #include "oslutils.h" 3 | #include "clintprogram.h" 4 | #include "clintscop.h" 5 | 6 | ClintProgram::ClintProgram(osl_scop_p scop, char *originalCode, QObject *parent) : 7 | QObject(parent), m_scop(scop) { 8 | 9 | // TODO: factory that concentrates osl-related creation? 10 | // AZ: I think it is okay for general objects (program, scop, stmt, stmtoccurence) to use osl. 11 | // They may accept a different constructor as long as they provide the same interface for the 12 | // coordinate system part. 13 | oslListForeach(scop, [this,originalCode](osl_scop_p sc) { 14 | ClintScop *vizScop = new ClintScop(sc, 6, originalCode, this); // FIXME: hardcoded value 15 | m_scops.push_back(vizScop); 16 | }); 17 | 18 | m_enumerator = new ISLEnumerator; 19 | } 20 | 21 | ClintProgram::~ClintProgram() { 22 | delete m_enumerator; 23 | } 24 | -------------------------------------------------------------------------------- /clintprogram.h: -------------------------------------------------------------------------------- 1 | #ifndef CLINTPROGRAM_H 2 | #define CLINTPROGRAM_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include "enumerator.h" 10 | 11 | class ClintStmt; 12 | class ClintScop; 13 | class VizCoordinateSystem; 14 | 15 | class ClintProgram : public QObject { 16 | Q_OBJECT 17 | public: 18 | explicit ClintProgram(osl_scop_p scop, char *originalCode = nullptr, QObject *parent = 0); 19 | ~ClintProgram(); 20 | 21 | QSet statementsInCoordinateSystem(VizCoordinateSystem *system) const { 22 | return csToStmt_.values(system).toSet(); 23 | } 24 | 25 | QSet coordinateSystemsForStatement(ClintStmt *stmt) const { 26 | return stmtToCS_.values(stmt).toSet(); 27 | } 28 | 29 | Enumerator *enumerator() const { 30 | return m_enumerator; 31 | } 32 | 33 | ClintScop *&operator [](int idx) { 34 | CLINT_ASSERT(idx < m_scops.size(), "Indexed access out of bounds"); 35 | return m_scops[idx]; 36 | } 37 | 38 | signals: 39 | 40 | public slots: 41 | 42 | private: 43 | // coordinate systems and statements should be children of this object 44 | /** Bidirectional mapping between visual scops and visual coordinates 45 | * systems they belong to */ 46 | QMultiHash stmtToCS_; 47 | QMultiHash csToStmt_; 48 | 49 | /** A vector of all scops in order of their execution flow */ 50 | QVector m_scops; 51 | 52 | osl_scop_p m_scop; 53 | 54 | Enumerator *m_enumerator; 55 | }; 56 | 57 | #endif // CLINTPROGRAM_H 58 | -------------------------------------------------------------------------------- /clintprojectionoverview.cpp: -------------------------------------------------------------------------------- 1 | #include "clintprojectionoverview.h" 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | ClintProjectionOverview::ClintProjectionOverview(ClintScop *cscop, QWidget *parent) : QWidget(parent) { 8 | resetProjectionMatrix(cscop); 9 | } 10 | 11 | void ClintProjectionOverview::resetProjectionMatrix(ClintScop *cscop) { 12 | for (auto element : m_allProjections) { 13 | VizProjection *projection = element.second; 14 | projection->setParent(nullptr); 15 | delete projection; 16 | } 17 | m_allProjections.clear(); 18 | 19 | if (m_layout != nullptr) { 20 | setLayout(nullptr); 21 | m_layout->setParent(nullptr); 22 | delete m_layout; 23 | } 24 | 25 | m_layout = new QGridLayout; 26 | for (int i = 0, e = cscop->dimensionality(); i < e - 1; i++) { 27 | for (int j = i + 1; j < e; j++) { 28 | VizProjection *projection = new VizProjection(i, j, this); 29 | projection->setViewActive(false); 30 | projection->projectScop(cscop); 31 | connect(projection, &VizProjection::selected, this, &ClintProjectionOverview::projectionSelected); 32 | m_layout->addWidget(projection->widget(), j-1, i); 33 | m_allProjections[std::make_pair(i, j)] = projection; 34 | } 35 | } 36 | m_layout->setContentsMargins(0, 0, 0, 0); 37 | setLayout(m_layout); 38 | } 39 | 40 | void ClintProjectionOverview::updateAllProjections() { 41 | for (auto element : m_allProjections) { 42 | VizProjection *projection = element.second; 43 | projection->updateProjection(); 44 | projection->updateInnerDependences(); 45 | projection->updateOuterDependences(); 46 | projection->updateInternalDependences(); 47 | } 48 | } 49 | 50 | void ClintProjectionOverview::updateRowColumn(int horizontalDim, int verticalDim) { 51 | for (auto element : m_allProjections) { 52 | int h, v; 53 | std::tie(h, v) = element.first; 54 | if (h != horizontalDim && v != verticalDim && h != verticalDim && v != horizontalDim) 55 | continue; 56 | 57 | VizProjection *projection = element.second; 58 | projection->updateProjection(); 59 | projection->updateInnerDependences(); 60 | projection->updateOuterDependences(); 61 | projection->updateInternalDependences(); 62 | } 63 | } 64 | 65 | void ClintProjectionOverview::updateProjection(int horizontalDim, int verticalDim) { 66 | auto iterator = m_allProjections.find(std::make_pair(horizontalDim, verticalDim)); 67 | if (iterator == std::end(m_allProjections)) { 68 | return; 69 | } 70 | iterator->second->updateProjection(); 71 | } 72 | 73 | VizProperties *ClintProjectionOverview::vizProperties() { 74 | if (m_allProjections.size() == 0) 75 | return nullptr; 76 | auto front = m_allProjections.begin(); 77 | return front->second->vizProperties(); 78 | } 79 | 80 | void ClintProjectionOverview::fillSvg(QSvgGenerator *generator) { 81 | QSize totalSize; 82 | for (auto element : m_allProjections) { 83 | VizProjection *projection = element.second; 84 | QSize size = projection->projectionSize(); 85 | totalSize.rwidth() += size.width(); 86 | totalSize.rheight() = qMax(totalSize.height(), size.height()); 87 | } 88 | generator->setSize(totalSize); 89 | QPainter *painter = new QPainter(generator); 90 | for (auto element : m_allProjections) { 91 | VizProjection *projection = element.second; 92 | QSize size = projection->projectionSize(); 93 | projection->paintProjection(painter); 94 | painter->setTransform(QTransform::fromTranslate(size.width(), 0), true); 95 | } 96 | 97 | delete painter; 98 | } 99 | -------------------------------------------------------------------------------- /clintprojectionoverview.h: -------------------------------------------------------------------------------- 1 | #ifndef CLINTPROJECTIONOVERVIEW_H 2 | #define CLINTPROJECTIONOVERVIEW_H 3 | 4 | #include 5 | 6 | #include 7 | #include 8 | 9 | #include "vizprojection.h" 10 | #include "vizproperties.h" 11 | 12 | class QGridLayout; 13 | class QSvgGenerator; 14 | 15 | class ClintProjectionOverview : public QWidget { 16 | Q_OBJECT 17 | public: 18 | explicit ClintProjectionOverview(ClintScop *cscop, QWidget *parent = nullptr); 19 | 20 | void resetProjectionMatrix(ClintScop *cscop); 21 | VizProperties *vizProperties(); 22 | void fillSvg(QSvgGenerator *generator); 23 | 24 | signals: 25 | void projectionSelected(int horizontalDim, int verticalDim); 26 | 27 | public slots: 28 | void updateAllProjections(); 29 | void updateProjection(int horizontalDim, int verticalDim); 30 | void updateRowColumn(int horizontalDim, int verticalDim); 31 | 32 | private: 33 | typedef std::map, VizProjection *> projectionMap; 34 | projectionMap m_allProjections = projectionMap(); 35 | QGridLayout *m_layout = nullptr; 36 | }; 37 | 38 | #endif // CLINTPROJECTIONOVERVIEW_H 39 | -------------------------------------------------------------------------------- /clintscop.h: -------------------------------------------------------------------------------- 1 | #ifndef CLINTSCOP_H 2 | #define CLINTSCOP_H 3 | 4 | #include 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #include "clintprogram.h" 13 | #include "transformation.h" 14 | #include "transformer.h" 15 | #include "dependenceanalyzer.h" 16 | 17 | class ClintDependence; 18 | class ClintStmt; 19 | class ClintStmtOccurrence; 20 | 21 | class ClintScop : public QObject { 22 | Q_OBJECT 23 | public: 24 | typedef std::map, ClintStmt *> VizBetaMap; 25 | typedef std::multimap, std::vector>, ClintDependence *> ClintDependenceMap; 26 | // typedef std::multimap, ClintDependence *> ClintDependenceMap; 27 | typedef std::multimap ClintOccurrenceDeps; 28 | 29 | explicit ClintScop(osl_scop_p scop, int parameterValue, char *originalCode = nullptr, ClintProgram *parent = nullptr); 30 | ~ClintScop(); 31 | 32 | // Accessors 33 | ClintProgram *program() const { 34 | return m_program; 35 | } 36 | 37 | const VizBetaMap &vizBetaMap() const { 38 | return m_vizBetaMap; 39 | } 40 | 41 | osl_relation_p fixedContext() const { 42 | return m_fixedContext; 43 | } 44 | 45 | std::unordered_set statements() const; 46 | 47 | ClintStmt *statement(const std::vector &beta) const { 48 | auto iterator = m_vizBetaMap.find(beta); 49 | if (iterator == std::end(m_vizBetaMap)) 50 | return nullptr; 51 | return iterator->second; 52 | } 53 | 54 | void transform(const Transformation &t) { 55 | TransformationGroup tg; 56 | tg.transformations.push_back(t); 57 | transform(tg); 58 | } 59 | 60 | void transform(const TransformationGroup &tg) { 61 | m_transformationSeq.groups.push_back(tg); 62 | for (const Transformation &transformation : tg.transformations) { 63 | // Remap betas when needed. FIXME: ClintScop should not know which transformation may modify betas 64 | // introduce bool Transformation::modifiesLoopStmtOrder() and use it. Same for checking for ISS transformation. 65 | if (transformation.kind() == Transformation::Kind::Fuse || 66 | transformation.kind() == Transformation::Kind::Split || 67 | transformation.kind() == Transformation::Kind::Reorder || 68 | transformation.kind() == Transformation::Kind::Tile || 69 | transformation.kind() == Transformation::Kind::Linearize || 70 | transformation.kind() == Transformation::Kind::Embed || 71 | transformation.kind() == Transformation::Kind::Unembed) { 72 | remapBetas(tg); 73 | break; 74 | } 75 | // XXX: needs rethinking 76 | // This weird move allows to workaround the 1-to-1 mapping condition imposed by the current implementation of remapBetas. 77 | // The problem is primarily caused by the fact of ClintStmtOccurrence creation in executeTransformationSequence (thus 78 | // apart from beta remapping) that happens in the undefined future; it is also not clear how to deal with multiple statements 79 | // being created by a transformation (which beta to assign to the remapped statement and which to the one being created; 80 | // is it important at all? occurrences will filter the scatterings they need, but not sure about dependence maps). 81 | // As long as VizManipulationManager deals with the association of VizPolyhedron to ClintStmtOccurrrence after it was created, 82 | // that part works fine. 83 | if (transformation.kind() == Transformation::Kind::IndexSetSplitting || 84 | transformation.kind() == Transformation::Kind::Collapse) { 85 | m_betaMapper->apply(nullptr, tg); 86 | break; 87 | } 88 | } 89 | } 90 | 91 | void executeTransformationSequence(); 92 | 93 | boost::optional guessInverseTransformation(const Transformation &transformation) { 94 | return m_transformer->guessInverseTransformation(appliedScop(), transformation); 95 | } 96 | 97 | ClintStmtOccurrence *occurrence(const std::vector &beta) const; 98 | std::unordered_set occurrences(const std::vector &betaPrefix) const; 99 | int lastValueInLoop(const std::vector &loopBeta) const; 100 | std::unordered_set internalDependences(ClintStmtOccurrence *occurrence) const; 101 | std::unordered_set dependencesBetween(ClintStmtOccurrence *occ1, ClintStmtOccurrence *occ2) const; 102 | std::vector untiledBetaVector(const std::vector &beta) const; 103 | const std::set &tilingDimensions(const std::vector &beta) const; 104 | 105 | void updateBetas(std::map, std::vector > &mapping); 106 | 107 | osl_scop_p appliedScop(); 108 | void appliedScopFlushCache(); 109 | 110 | void swapBetaMapper(ClintScop *scop) { 111 | std::swap(m_betaMapper, scop->m_betaMapper); 112 | } 113 | 114 | osl_scop_p scopPart() const { 115 | return m_scopPart; 116 | } 117 | const TransformationSequence &transformationSequence() const { 118 | return m_transformationSeq; 119 | } 120 | const TransformationSequence &redoSequence() const { 121 | return m_undoneTransformationSeq; 122 | } 123 | void resetRedoSequence(const TransformationSequence &seq) { 124 | m_undoneTransformationSeq = seq; 125 | } 126 | 127 | const char *generatedCode() { 128 | return m_generatedCode; 129 | } 130 | 131 | const char *originalCode() { 132 | return m_originalCode; 133 | } 134 | 135 | const char *currentScript() { 136 | return m_currentScript; 137 | } 138 | 139 | const char *generatedHtml() const { 140 | return m_generatedHtml.c_str(); 141 | } 142 | 143 | const char *originalHtml() const { 144 | return m_originalHtml.c_str(); 145 | } 146 | 147 | bool hasUndo() const { 148 | return m_transformationSeq.groups.size() > 0; 149 | } 150 | 151 | bool hasRedo() const { 152 | return m_undoneTransformationSeq.groups.size() > 0; 153 | } 154 | 155 | std::vector parameterValues() const { 156 | std::vector parameters(m_scopPart->context->nb_parameters, m_parameterValue); 157 | return std::move(parameters); 158 | } 159 | 160 | int dimensionality(); 161 | 162 | void tile(const std::vector &betaPrefix, int dimensionIdx, int tileSize); 163 | void untile(const std::vector &betaPrefix, int dimensionIdx); 164 | 165 | /// Get the single original beta of an occurrence even if it has multiple original betas in mapper. 166 | /// This function is used as default policy for finding the original occurrence for a transformed one. 167 | std::vector canonicalOriginalBetaVector(const std::vector &beta) const; 168 | 169 | signals: 170 | void transformExecuted(); 171 | void dimensionalityChanged(); 172 | 173 | public slots: 174 | void undoTransformation(); 175 | void redoTransformation(); 176 | void clearRedo(); 177 | 178 | private: 179 | void updateGeneratedHtml(osl_scop_p transformedScop, std::string &string); 180 | void forwardDependencesBetween(ClintStmtOccurrence *occ1, ClintStmtOccurrence *occ2, 181 | std::unordered_set &result) const; 182 | void clearDependences(); 183 | void processDependenceMap(const DependenceAnalyzer::DependenceMap &dependenceMap); 184 | void createDependences(osl_scop_p scop); 185 | void updateDependences(osl_scop_p transformed); 186 | void resetOccurrences(osl_scop_p transformed); 187 | 188 | void remapBetas(const TransformationGroup &tg); 189 | 190 | osl_scop_p m_scopPart; 191 | osl_scop_p m_appliedScopCache = nullptr; 192 | ClintProgram *m_program; 193 | int m_parameterValue; 194 | osl_relation_p m_fixedContext; 195 | // std::vector statements_; 196 | // statements = unique values of m_vizBetaMap 197 | VizBetaMap m_vizBetaMap; 198 | ClintDependenceMap m_dependenceMap; 199 | ClintOccurrenceDeps m_internalDeps; 200 | 201 | TransformationSequence m_transformationSeq; 202 | TransformationSequence m_undoneTransformationSeq; 203 | Transformer *m_transformer; 204 | Transformer *m_scriptGenerator; 205 | ClayBetaMapper *m_betaMapper; 206 | size_t m_groupsExecuted = 0; 207 | DependenceAnalyzer *m_analyzer; 208 | 209 | char *m_originalCode = nullptr; 210 | char *m_generatedCode = nullptr; 211 | char *m_currentScript = nullptr; 212 | std::stringstream m_scriptStream; 213 | std::string m_originalHtml, m_generatedHtml; 214 | }; 215 | 216 | #endif // CLINTSCOP_H 217 | -------------------------------------------------------------------------------- /clintstmt.cpp: -------------------------------------------------------------------------------- 1 | #include "enumerator.h" 2 | #include "macros.h" 3 | #include "oslutils.h" 4 | #include "clintstmt.h" 5 | #include "clintstmtoccurrence.h" 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | inline void fillDimensionNames(char **strings, std::vector &dimensionNames) { 13 | for (char **str = strings; str != nullptr && *str != nullptr; str++) { 14 | dimensionNames.emplace_back(*str); 15 | } 16 | } 17 | 18 | ClintStmt::ClintStmt(osl_statement_p stmt, ClintScop *parent) : 19 | QObject(parent), m_scop(parent) { 20 | 21 | // FIXME: redoing iteration over scattering union parts 22 | oslListForeach(stmt->scattering, [this,stmt](osl_relation_p scattering) { 23 | std::vector betaVector = betaExtract(scattering); 24 | if (m_occurrences.count(betaVector) == 0) { 25 | makeOccurrence(stmt, betaVector); 26 | } 27 | }); 28 | 29 | // Get dimension names for the statement. 30 | // Try to find iterator names in either body or extbody. 31 | void *bodyGeneric = osl_generic_lookup(stmt->extension, OSL_URI_BODY); 32 | void *extbodyGeneric = osl_generic_lookup(stmt->extension, OSL_URI_EXTBODY); 33 | void *namesGeneric = osl_generic_lookup(m_scop->scopPart()->extension, OSL_URI_SCATNAMES); 34 | osl_body_p body = nullptr; 35 | if (bodyGeneric) { 36 | body = static_cast(bodyGeneric); 37 | } else if (extbodyGeneric) { 38 | osl_extbody_p extbody = static_cast(extbodyGeneric); 39 | body = extbody->body; 40 | } 41 | 42 | // If iterators found, use them. Create default names otherwise. 43 | // FIXME(osl): we have multiple places where iterator names are placed 44 | // body, extbody's body and scatnames. 45 | if (namesGeneric) { 46 | osl_strings_p betaIterators = static_cast(namesGeneric)->names; 47 | for (int i = 1, e = osl_strings_size(betaIterators); i < e; i += 2) { 48 | m_dimensionNames.emplace_back(betaIterators->string[i]); 49 | } 50 | } else if (body && body->iterators) { 51 | fillDimensionNames(body->iterators->string, m_dimensionNames); 52 | } else { 53 | int nbIterators = 0; 54 | oslListForeach(stmt->domain, [&nbIterators](osl_relation_p domain) mutable { 55 | nbIterators = std::max(nbIterators, domain->nb_output_dims); 56 | }); 57 | // Create at least 1 name of each type to avoid weird memory allocations. 58 | static char letters[] = "piyzl"; // Have modifiable chars so that C++11 compiler does not complain on old osl C function. 59 | osl_names_p names = osl_names_generate(&letters[0], 1, &letters[1], nbIterators, &letters[2], 1, &letters[3], 1, &letters[4], 1); 60 | fillDimensionNames(names->iterators->string, m_dimensionNames); 61 | osl_names_free(names); 62 | } 63 | } 64 | 65 | void ClintStmt::updateBetas(const std::map, std::vector > &mapping) { 66 | std::map, ClintStmtOccurrence *> updatedBetas; 67 | std::set> keysToRemove; 68 | for (auto it : m_occurrences) { 69 | if (mapping.count(it.first) == 1) { 70 | updatedBetas[mapping.at(it.first)] = it.second; 71 | keysToRemove.insert(it.first); 72 | } 73 | } 74 | for (auto it : keysToRemove) { 75 | m_occurrences.erase(it); 76 | } 77 | for (auto it : updatedBetas) { 78 | m_occurrences.insert(it); 79 | } 80 | } 81 | 82 | std::vector ClintStmt::occurrences() const { 83 | std::vector result; 84 | for (auto occurence : m_occurrences) { 85 | result.push_back(occurence.second); 86 | } 87 | std::sort(std::begin(result), std::end(result), VizStmtOccurrencePtrComparator()); 88 | return std::move(result); 89 | } 90 | 91 | ClintStmtOccurrence *ClintStmt::makeOccurrence(osl_statement_p stmt, const std::vector &beta) { 92 | ClintStmtOccurrence *occurrence = new ClintStmtOccurrence(stmt, beta, this); 93 | m_occurrences[beta] = occurrence; 94 | return occurrence; 95 | } 96 | 97 | ClintStmtOccurrence *ClintStmt::splitOccurrence(ClintStmtOccurrence *occurrence, const std::vector &beta) { 98 | ClintStmtOccurrence *otherOccurrence = occurrence->split(beta); 99 | m_occurrences[beta] = otherOccurrence; 100 | return otherOccurrence; 101 | } 102 | 103 | void ClintStmt::removeOccurrence(ClintStmtOccurrence *occurrence) { 104 | const std::vector beta = occurrence->betaVector(); 105 | m_occurrences.erase(beta); 106 | delete occurrence; 107 | } 108 | -------------------------------------------------------------------------------- /clintstmt.h: -------------------------------------------------------------------------------- 1 | #ifndef CLINTSTMT_H 2 | #define CLINTSTMT_H 3 | 4 | #include 5 | 6 | #include "clintprogram.h" 7 | #include "clintscop.h" 8 | 9 | #include 10 | #include 11 | 12 | class ClintStmtOccurrence; 13 | 14 | class ClintStmt : public QObject { 15 | Q_OBJECT 16 | public: 17 | explicit ClintStmt(osl_statement_p stmt, ClintScop *parent = nullptr); 18 | 19 | ClintScop *scop() const { 20 | return m_scop; 21 | } 22 | 23 | ClintProgram *program() const { 24 | return m_scop->program(); 25 | } 26 | 27 | std::vector occurrences() const; 28 | 29 | ClintStmtOccurrence *occurrence(const std::vector &beta) const { 30 | auto iterator = m_occurrences.find(beta); 31 | if (iterator == std::end(m_occurrences)) 32 | return nullptr; 33 | return iterator->second; 34 | } 35 | 36 | ClintStmtOccurrence *makeOccurrence(osl_statement_p stmt, const std::vector &beta); 37 | ClintStmtOccurrence *splitOccurrence(ClintStmtOccurrence *occurrence, const std::vector &beta); 38 | void removeOccurrence(ClintStmtOccurrence *occurrence); 39 | 40 | std::string dimensionName(int dimension) const { 41 | CLINT_ASSERT(dimension >= 0, "Dimension index should be positive"); 42 | if (dimension < m_dimensionNames.size()) 43 | return m_dimensionNames[dimension]; 44 | // CLINT_UNREACHABLE; 45 | return std::string("??"); 46 | } 47 | 48 | void updateBetas(const std::map, std::vector> &mapping); 49 | 50 | signals: 51 | 52 | public slots: 53 | 54 | private: 55 | ClintScop *m_scop; 56 | std::map, ClintStmtOccurrence *> m_occurrences; 57 | std::vector m_dimensionNames; 58 | }; 59 | 60 | #endif // CLINTSTMT_H 61 | -------------------------------------------------------------------------------- /clintstmtoccurrence.h: -------------------------------------------------------------------------------- 1 | #ifndef CLINTSTMTOCCURRENCE_H 2 | #define CLINTSTMTOCCURRENCE_H 3 | 4 | #include "clintstmt.h" 5 | 6 | #include 7 | #include 8 | 9 | #include 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | class ClintStmtOccurrence : public QObject { 17 | Q_OBJECT 18 | public: 19 | ClintStmtOccurrence(osl_statement_p stmt, 20 | const std::vector &betaVector, 21 | ClintStmt *parent = 0); 22 | 23 | ClintStmtOccurrence *split(const std::vector &betaVector); 24 | 25 | friend bool operator < (const ClintStmtOccurrence &lhs, const ClintStmtOccurrence &rhs); 26 | friend bool operator ==(const ClintStmtOccurrence &lhs, const ClintStmtOccurrence &rhs); 27 | 28 | int ignoreTilingDim(int dimension) const; 29 | std::vector> projectOn(int horizontalDimIdx, int verticalDimIdx) const; 30 | std::pair, std::pair> parseProjectedPoint(std::vector point, 31 | int horizontalDimIdx, int verticalDimIdx) const; 32 | 33 | int dimensionality() const { 34 | return static_cast(m_betaVector.size()) 35 | - std::count_if(std::begin(m_tilingDimensions), std::end(m_tilingDimensions), [](int i) { return i % 2 == 0;}) 36 | - 1; 37 | } 38 | 39 | ClintStmt *statement() const { 40 | return m_statement; 41 | } 42 | 43 | ClintProgram *program() const { 44 | return m_statement->program(); 45 | } 46 | 47 | ClintScop *scop() const { 48 | return m_statement->scop(); 49 | } 50 | 51 | const std::vector &betaVector() const { 52 | return m_betaVector; 53 | } 54 | 55 | int visibleDimensionality() const { 56 | // TODO: this should actually be a computation of explicitly-defined dimensions 57 | // we make take it from chlore, but for now we assume the relation is well-defined, i.e. 58 | // there are as many explicit defintions as input dimensions (global validity). 59 | return m_oslScattering->nb_input_dims; 60 | } 61 | 62 | int inputDimensionality() const { 63 | return m_oslScattering->nb_input_dims; 64 | } 65 | 66 | const std::set &tilingDimensions() const { 67 | return m_tilingDimensions; 68 | } 69 | 70 | void tile(int dimensionIdx, unsigned tileSize); 71 | void untile(int dimensionIdx); 72 | 73 | bool isTiled() const { 74 | return !m_tilingDimensions.empty(); 75 | } 76 | 77 | bool isTiled(int dimension) const { 78 | dimension = ignoreTilingDim(dimension); 79 | return m_tilingDimensions.find(dimension - 2) != std::end(m_tilingDimensions); 80 | } 81 | 82 | // dimIdx -- projection dimension, 0-based 83 | bool isProjectionTiled(int dimIdx) const { 84 | return projectionDimTileSize(dimIdx) != 0; 85 | } 86 | 87 | unsigned projectionDimTileSize(int dimIdx) const { 88 | int scatteringDim = 2 * (depth(dimIdx) - 1) - 1; // +1 for the alpha-dim, -2 to look for previous tiling. 89 | auto it = m_tileSizes.find(scatteringDim); 90 | if (it != std::end(m_tileSizes)) 91 | return it->second; 92 | return 0; 93 | } 94 | 95 | unsigned tileSize(int dim) const { 96 | if (m_tilingDimensions.find(dim) == std::end(m_tilingDimensions)) { 97 | return 0; 98 | } 99 | CLINT_ASSERT(m_tileSizes.find(dim) != std::end(m_tileSizes), 100 | "Dimension is tiled, but no tile size associated."); // Probably, a beta dimension. 101 | return m_tileSizes.at(dim); 102 | } 103 | 104 | /** 105 | * Get the 1-based depth that may be used for transformation. 106 | * Takes tiling dimensions into account. 107 | * \param[in] dimension 0-based visible dimension index. 108 | * \returns 1-based depth for Clay transformations. 109 | */ 110 | size_t depth(size_t dimension) const { 111 | size_t scatDimension = 2 * dimension + 1; 112 | size_t scatDimensionNb = (m_betaVector.size() - 1) * 2 + 1; 113 | CLINT_ASSERT(scatDimension < scatDimensionNb, 114 | "Dimension overflow"); 115 | size_t result = dimension + 1; 116 | for (size_t i = 1; i <= scatDimension; i += 2) { 117 | if (m_tilingDimensions.count(i)) { 118 | scatDimension += 2; 119 | result++; 120 | } 121 | } 122 | return result; 123 | } 124 | 125 | std::vector untiledBetaVector() const; 126 | std::vector canonicalOriginalBetaVector() const { 127 | return scop()->canonicalOriginalBetaVector(m_betaVector); 128 | } 129 | 130 | int minimumValue(int dimIdx) const; 131 | int maximumValue(int dimIdx) const; 132 | 133 | void resetOccurrence(osl_statement_p stmt, const std::vector &betaVector); 134 | void resetBetaVector(const std::vector &betaVector); 135 | 136 | enum class Bound { 137 | LOWER, 138 | UPPER 139 | }; 140 | 141 | std::vector findBoundlikeForm(Bound bound, int dimIdx, int constValue); 142 | 143 | 144 | void debugDumpMinMaxCache(std::ostream &out) { 145 | out << "Minima: " << std::endl; 146 | for (auto v : m_cachedDimMins) { 147 | out << v.first << " : " << v.second << std::endl; 148 | } 149 | out << "Maxima: " << std::endl; 150 | for (auto v : m_cachedDimMaxs) { 151 | out << v.first << " : " << v.second << std::endl; 152 | } 153 | out << std::endl; 154 | } 155 | 156 | signals: 157 | void pointsChanged(); 158 | void betaChanged(); 159 | 160 | public slots: 161 | 162 | private: 163 | osl_relation_p m_oslScattering = nullptr; 164 | osl_statement_p m_oslStatement; /// Pointer to the transformed osl statement of this occurrence. This actually belongs to ClintStmt. 165 | std::vector m_betaVector; 166 | std::set m_tilingDimensions; 167 | ClintStmt *m_statement; 168 | // FIXME: m_tilingDImensions just duplicates the set of keys of m_tileSizes. 169 | std::unordered_map m_tileSizes; 170 | 171 | // Caches for min/max (index = visible dimension, not computed for tiled). 172 | mutable std::unordered_map m_cachedDimMins; 173 | mutable std::unordered_map m_cachedDimMaxs; 174 | 175 | void computeMinMax(const std::vector> &points, 176 | int horizontalDimIdx, int verticalDimIdx) const; 177 | std::vector makeBoundlikeForm(Bound bound, int dimIdx, int constValue, int constantBoundaryPart, const std::vector ¶meters, const std::vector ¶meterValues); 178 | }; 179 | 180 | struct VizStmtOccurrencePtrComparator { 181 | bool operator () (const ClintStmtOccurrence *lhs, const ClintStmtOccurrence *rhs) { 182 | return *lhs < *rhs; 183 | } 184 | }; 185 | 186 | #endif // CLINTSTMTOCCURRENCE_H 187 | -------------------------------------------------------------------------------- /clintwindow.h: -------------------------------------------------------------------------------- 1 | #ifndef CLINTWINDOW_H 2 | #define CLINTWINDOW_H 3 | 4 | #include 5 | #include 6 | 7 | #include "clintprogram.h" 8 | #include "clintprojectionoverview.h" 9 | #include "vizprojection.h" 10 | #include "vizproperties.h" 11 | 12 | class QWidget; 13 | class QTextEdit; 14 | 15 | class ClintWindow : public QMainWindow { 16 | Q_OBJECT 17 | public: 18 | explicit ClintWindow(QWidget *parent = 0); 19 | ~ClintWindow(); 20 | 21 | void regenerateScop(osl_scop_p originalScop = nullptr); 22 | void regenerateScop(const TransformationSequence &sequence); 23 | void createProjections(ClintScop *vscop); 24 | void paintTogether(QPainter *painter, QSvgGenerator *generator); 25 | 26 | signals: 27 | 28 | public slots: 29 | void fileOpen(); 30 | void fileClose(); 31 | void fileSaveSvg(); 32 | void openFileByName(QString fileName); 33 | 34 | void editUndo(); 35 | void editRedo(); 36 | void editVizProperties(); 37 | 38 | void viewFreezeToggled(bool value); 39 | void viewProjectionMatrixToggled(bool value); 40 | 41 | void scopTransformed(); 42 | 43 | void updateCodeEditor(); 44 | void reparseCode(); 45 | void reparseScript(); 46 | 47 | void changeParameter(int value); 48 | void projectionSelectedInOverview(int horizontal, int vertical); 49 | void projectionSelectedAlone(int horizontal, int vertical); 50 | 51 | private: 52 | QAction *m_actionFileOpen; 53 | QAction *m_actionFileClose; 54 | QAction *m_actionFileSaveSvg; 55 | QAction *m_actionFileQuit; 56 | 57 | QAction *m_actionEditUndo; 58 | QAction *m_actionEditRedo; 59 | QAction *m_actionEditVizProperties; 60 | 61 | QAction *m_actionViewFreeze; 62 | QAction *m_actionViewProjectionMatrix; 63 | 64 | QMenuBar *m_menuBar; 65 | 66 | bool m_fileOpen = false; 67 | 68 | ClintProgram *m_program = nullptr; 69 | VizProjection *m_projection = nullptr; 70 | ClintProjectionOverview *m_projectionOverview = nullptr; 71 | QWidget *m_graphicalInterface = nullptr; 72 | QTextEdit *m_codeEditor = nullptr; 73 | QTextEdit *m_scriptEditor = nullptr; 74 | QPushButton *m_reparseCodeButton = nullptr, 75 | *m_reparseScriptButton = nullptr; 76 | 77 | bool m_showOriginalCode = false; 78 | int m_parameterValue = 6; 79 | size_t m_horizontalDimSelected = VizProperties::NO_DIMENSION, 80 | m_verticalDimSelected = VizProperties::NO_DIMENSION; 81 | QString m_fileBasename; 82 | 83 | void setupActions(); 84 | void setupMenus(); 85 | 86 | void resetCentralWidget(QWidget *interface = nullptr); 87 | ClintScop *regenerateScopWithSequence(osl_scop_p originalScop, const TransformationSequence &sequence); 88 | void deleteProjectionOverview(); 89 | void deleteProjection(); 90 | }; 91 | 92 | #endif // CLINTWINDOW_H 93 | -------------------------------------------------------------------------------- /cmake-uninstall.cmake.in: -------------------------------------------------------------------------------- 1 | if(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt") 2 | message(FATAL_ERROR "Cannot find install manifest: @CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt") 3 | endif(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt") 4 | 5 | file(READ "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt" files) 6 | string(REGEX REPLACE "\n" ";" files "${files}") 7 | foreach(file ${files}) 8 | message(STATUS "Uninstalling $ENV{DESTDIR}${file}") 9 | if(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}") 10 | exec_program( 11 | "@CMAKE_COMMAND@" ARGS "-E remove \"$ENV{DESTDIR}${file}\"" 12 | OUTPUT_VARIABLE rm_out 13 | RETURN_VALUE rm_retval 14 | ) 15 | if(NOT "${rm_retval}" STREQUAL 0) 16 | message(FATAL_ERROR "Problem when removing $ENV{DESTDIR}${file}") 17 | endif(NOT "${rm_retval}" STREQUAL 0) 18 | else(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}") 19 | message(STATUS "File $ENV{DESTDIR}${file} does not exist.") 20 | endif(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}") 21 | endforeach(file) 22 | -------------------------------------------------------------------------------- /dependenceanalyzer.cpp: -------------------------------------------------------------------------------- 1 | #include "dependenceanalyzer.h" 2 | #include "macros.h" 3 | #include "oslutils.h" 4 | 5 | #include 6 | 7 | DependenceAnalyzer::DependenceAnalyzer() { 8 | } 9 | 10 | DependenceAnalyzer::~DependenceAnalyzer() { 11 | } 12 | 13 | CandlAnalyzer::CandlAnalyzer() { 14 | } 15 | 16 | CandlAnalyzer::~CandlAnalyzer() { 17 | } 18 | 19 | 20 | osl_dependence_p CandlAnalyzer::scopDependences(osl_scop_p scop) { 21 | candl_scop_usr_init(scop); 22 | osl_dependence_p dependences = candl_dependence(scop, m_candlOptions); 23 | if (dependences) 24 | candl_dependence_init_fields(scop, dependences); 25 | candl_scop_usr_cleanup(scop); 26 | return dependences; 27 | } 28 | 29 | std::pair CandlAnalyzer::scopViolations(osl_scop_p original, osl_scop_p transformed) { 30 | osl_dependence_p dependences; 31 | candl_violation_p violations = candl_violation(original, transformed, &dependences, m_candlOptions); 32 | return std::make_pair(violations, dependences); 33 | } 34 | 35 | DependenceAnalyzer::DependenceMap CandlAnalyzer::constructDependenceMap(osl_dependence_p dependence) { 36 | DependenceMap dependenceMap; 37 | oslListForeachSingle(dependence, [&dependenceMap](osl_dependence_p dep) { 38 | CLINT_ASSERT(dep->stmt_source_ptr != nullptr, 39 | "Source statement pointer in the osl dependence must be defined"); 40 | CLINT_ASSERT(dep->stmt_target_ptr != nullptr, 41 | "Target statement pointer in the osl dependence must be defined"); 42 | 43 | std::vector sourceBeta = betaExtract(dep->stmt_source_ptr->scattering); 44 | std::vector targetBeta = betaExtract(dep->stmt_target_ptr->scattering); 45 | dep->stmt_source_ptr = nullptr; // Set up nulls intentionally, the data will be deleted. 46 | dep->stmt_target_ptr = nullptr; 47 | dependenceMap.emplace(std::make_pair(sourceBeta, targetBeta), 48 | std::make_pair(dep, false)); 49 | }); 50 | return std::move(dependenceMap); 51 | } 52 | 53 | DependenceAnalyzer::DependenceMap CandlAnalyzer::analyze(osl_scop_p original, osl_scop_p transformed) { 54 | osl_dependence_p dependences; 55 | std::unordered_set violatedDependences; 56 | if (transformed != nullptr) { 57 | candl_violation_p violations; 58 | std::tie(violations, dependences) = scopViolations(original, transformed); 59 | oslListForeach(violations, [&violatedDependences](candl_violation_p violation){ 60 | violatedDependences.insert(violation->dependence); 61 | }); 62 | } else { 63 | dependences = scopDependences(original); 64 | } 65 | 66 | DependenceMap dependenceMap = constructDependenceMap(dependences); 67 | for (auto &el : dependenceMap) { 68 | if (violatedDependences.find(el.second.first) != violatedDependences.end()) { 69 | el.second.second = true; 70 | } 71 | } 72 | 73 | return dependenceMap; 74 | } 75 | -------------------------------------------------------------------------------- /dependenceanalyzer.h: -------------------------------------------------------------------------------- 1 | #ifndef DEPENDENCEANALYZER_H 2 | #define DEPENDENCEANALYZER_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | #include 10 | 11 | class DependenceAnalyzer { 12 | public: 13 | typedef std::pair Dependence; 14 | typedef std::multimap, std::vector>, 15 | Dependence> DependenceMap; 16 | 17 | DependenceAnalyzer(); 18 | virtual ~DependenceAnalyzer(); 19 | 20 | virtual DependenceMap analyze(osl_scop_p original, 21 | osl_scop_p transformed = nullptr) = 0; 22 | }; 23 | 24 | class CandlRAII { 25 | public: 26 | CandlRAII() { 27 | m_options = candl_options_malloc(); 28 | m_options->fullcheck = 1; 29 | } 30 | 31 | ~CandlRAII() { 32 | candl_options_free(m_options); 33 | } 34 | 35 | operator candl_options_p () { 36 | return m_options; 37 | } 38 | 39 | private: 40 | candl_options_p m_options; 41 | }; 42 | 43 | class CandlAnalyzer : public DependenceAnalyzer{ 44 | public: 45 | CandlAnalyzer(); 46 | virtual ~CandlAnalyzer(); 47 | 48 | DependenceMap analyze(osl_scop_p original, osl_scop_p transformed = nullptr); 49 | 50 | private: 51 | CandlRAII m_candlOptions; 52 | 53 | DependenceMap constructDependenceMap(osl_dependence_p dependence); 54 | std::pair scopViolations(osl_scop_p original, osl_scop_p transformed); 55 | osl_dependence_p scopDependences(osl_scop_p scop); 56 | 57 | }; 58 | 59 | #endif // DEPENDENCEANALYZER_H 60 | -------------------------------------------------------------------------------- /enumerator.cpp: -------------------------------------------------------------------------------- 1 | #include "enumerator.h" 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | /// Application-wide ISL context 8 | ISLContextRAII ISLEnumerator::m_islContext; 9 | 10 | const int Enumerator::NO_COORD; 11 | const int Enumerator::NO_DIMENSION; 12 | 13 | namespace { 14 | isl_stat addISLPointToVector(isl_point *point, void *vect) { 15 | CLINT_ASSERT(point != nullptr, "Point is nullptr"); 16 | CLINT_ASSERT(vect != nullptr, "Vector is nullptr"); 17 | 18 | std::vector > &vector = *static_cast > *>(vect); 19 | isl_space *space = isl_point_get_space(point); 20 | const unsigned nbDims = isl_space_dim(space, isl_dim_all); 21 | std::vector pointVector; 22 | pointVector.reserve(nbDims); 23 | for (unsigned i = 0; i < nbDims; i++) { 24 | isl_val *val = isl_point_get_coordinate_val(point, isl_dim_all, i); 25 | long value = isl_val_get_num_si(val); 26 | CLINT_ASSERT(isl_val_get_den_si(val) == 1, "Fractional point"); 27 | CLINT_ASSERT(value <= INT_MAX, "Integer overflow"); 28 | int ivalue = static_cast(value); 29 | pointVector.push_back(ivalue); 30 | isl_val_free(val); 31 | } 32 | isl_space_free(space); 33 | isl_point_free(point); 34 | vector.push_back(std::move(pointVector)); 35 | 36 | return isl_stat_ok; 37 | } 38 | } // end anonymous namespace 39 | 40 | std::vector > ISLEnumerator::enumerate(osl_relation_p relation, const std::vector &dimensions) { 41 | isl_set *set = setFromOSLRelation(relation); 42 | 43 | std::vector > points; 44 | std::vector allDimensions, dimensionsToProjectOut; 45 | // Fill non-local dimension indices. 46 | allDimensions.reserve(relation->nb_columns - 2); 47 | for (int i = 0; i < relation->nb_columns - 2; i++) { 48 | if (i < relation->nb_input_dims + relation->nb_output_dims || 49 | i >= relation->nb_input_dims + relation->nb_output_dims + relation->nb_local_dims) { 50 | allDimensions.push_back(i); 51 | } 52 | } 53 | dimensionsToProjectOut.reserve(allDimensions.size() - dimensions.size()); 54 | std::set_difference(std::begin(allDimensions), 55 | std::end(allDimensions), 56 | std::begin(dimensions), 57 | std::end(dimensions), 58 | std::back_inserter(dimensionsToProjectOut)); 59 | 60 | // Sort dimensions to project out in the descending order. 61 | // Thus, the projection will not change the indices of the next dimensions to project out. 62 | std::sort(std::begin(dimensionsToProjectOut), std::end(dimensionsToProjectOut), std::greater()); 63 | for (int dim : dimensionsToProjectOut) { 64 | isl_dim_type dim_type; 65 | int index; 66 | std::tuple tuple = ISLEnumerator::dimFromOSL(relation, dim); 67 | std::tie(dim_type, index) = tuple; 68 | set = isl_set_project_out(set, dim_type, index, 1); 69 | } 70 | isl_set_foreach_point(set, &addISLPointToVector, &points); 71 | isl_set_free(set); 72 | return std::move(points); // Force RVO. 73 | } 74 | 75 | osl_relation_p ISLEnumerator::scheduledDomain(osl_relation_p domain, osl_relation_p schedule) { 76 | CLINT_ASSERT(domain->nb_input_dims == 0, "Domain is not a set"); 77 | CLINT_ASSERT(domain->nb_parameters == schedule->nb_parameters, 78 | "Domain and schedule have different sets of parameters"); 79 | 80 | isl_set *islDomain = setFromOSLRelation(domain); 81 | isl_map *islSchedule = mapFromOSLRelation(schedule); 82 | isl_set *islScheduledDomain = 83 | isl_set_apply(islDomain, islSchedule); 84 | osl_relation_p result = setToOSLRelation(islScheduledDomain); 85 | isl_set_free(islScheduledDomain); 86 | return result; 87 | } 88 | 89 | ISLEnumerator::~ISLEnumerator() { 90 | } 91 | -------------------------------------------------------------------------------- /enumerator.h: -------------------------------------------------------------------------------- 1 | #ifndef ENUMERATOR_H 2 | #define ENUMERATOR_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #include "macros.h" 16 | 17 | class Enumerator { 18 | public: 19 | /** 20 | * @brief Get a list of integer points in the polytope, projected to a set of specific dimensions. 21 | * @param [in] relation Union of relations that defines a polytope. 22 | * @param [in] dimensions Vector of indices of dimensions to project points onto. 23 | * @return The vector of integer points inside the polyhedron, each point represented as a vector of integer coordinates ordered 24 | * by the dimension index. 25 | */ 26 | virtual std::vector> enumerate(osl_relation_p relation, const std::vector &dimensions) = 0; 27 | /** 28 | * @brief Virtual desctructor. Reimplement in all derived classes with non-trival memory management. 29 | */ 30 | virtual ~Enumerator() {} 31 | 32 | const static int NO_COORD = INT_MAX; 33 | const static int NO_DIMENSION = -2; 34 | }; 35 | 36 | class ISLContextRAII { 37 | public: 38 | ISLContextRAII() { 39 | } 40 | 41 | ~ISLContextRAII() { 42 | isl_ctx_free(m_ctx); 43 | } 44 | 45 | isl_ctx *ctx() { 46 | if (m_ctx == nullptr) { 47 | m_ctx = isl_ctx_alloc(); 48 | } 49 | return m_ctx; 50 | } 51 | 52 | isl_ctx *operator ()() { 53 | return ctx(); 54 | } 55 | 56 | operator isl_ctx *() { 57 | return ctx(); 58 | } 59 | 60 | private: 61 | isl_ctx *m_ctx; 62 | }; 63 | 64 | /** 65 | * @brief An implementation of Enumerator using ISL library. 66 | */ 67 | class ISLEnumerator : public Enumerator { 68 | public: 69 | std::vector > enumerate(osl_relation_p relation, const std::vector &dimensions) override; 70 | 71 | ~ISLEnumerator() override; 72 | 73 | static std::tuple dimFromOSL(osl_relation_p relation, int dimension) { 74 | CLINT_ASSERT(dimension >= 0, "Negative dimension"); 75 | CLINT_ASSERT(dimension < relation->nb_columns - 2, "Dimension overflow"); 76 | if (dimension < relation->nb_output_dims) 77 | return std::make_tuple(isl_dim_out, dimension); 78 | dimension -= relation->nb_output_dims; 79 | if (dimension < relation->nb_input_dims) 80 | return std::make_tuple(isl_dim_in, dimension); 81 | dimension -= relation->nb_input_dims; 82 | if (dimension < relation->nb_local_dims) 83 | CLINT_ASSERT(false, "Local dimensions are not directly accessible in ISL"); 84 | dimension -= relation->nb_local_dims; 85 | if (dimension < relation->nb_parameters) 86 | return std::make_tuple(isl_dim_param, dimension); 87 | 88 | CLINT_UNREACHABLE; 89 | } 90 | 91 | static inline __isl_give isl_set *setFromOSLRelation(osl_relation_p relation, osl_names_p names = nullptr) { 92 | CLINT_ASSERT(relation->nb_input_dims == 0, "Relation is not a set"); 93 | return osl2isl(isl_set_read_from_str, relation, names); 94 | } 95 | 96 | static inline __isl_give isl_map *mapFromOSLRelation(osl_relation_p relation, osl_names_p names = nullptr) { 97 | return osl2isl(isl_map_read_from_str, relation, names); 98 | } 99 | 100 | static inline __isl_give isl_basic_set *basicSetFromOSLRelation(osl_relation_p relation, osl_names_p names = nullptr) { 101 | CLINT_ASSERT(relation->nb_input_dims == 0, "Relation is not a set"); 102 | return osl2isl(isl_basic_set_read_from_str, relation, names); 103 | } 104 | 105 | static inline __isl_give isl_basic_map *basicMapFromOSLRelation(osl_relation_p relation, osl_names_p names = nullptr) { 106 | return osl2isl(isl_basic_map_read_from_str, relation, names); 107 | } 108 | 109 | static inline osl_relation_p setToOSLRelation(isl_set *set) { 110 | return isl2osl(isl_printer_print_set, set); 111 | } 112 | 113 | static inline osl_relation_p basicSetToOSLRelation(isl_basic_set *basicSet) { 114 | return isl2osl(isl_printer_print_basic_set, basicSet); 115 | } 116 | 117 | static inline osl_relation_p mapToOSLRelation(isl_map *map) { 118 | return isl2osl(isl_printer_print_map, map); 119 | } 120 | 121 | static osl_relation_p scheduledDomain(osl_relation_p domain, osl_relation_p schedule); 122 | 123 | private: 124 | static ISLContextRAII m_islContext; 125 | 126 | template 127 | static osl_relation_p isl2osl(isl_printer *(&Func)(isl_printer *, T *), T *t) { 128 | CLINT_ASSERT(t != nullptr, "ISL object is null"); 129 | 130 | isl_printer *prn = isl_printer_to_str(m_islContext); 131 | prn = isl_printer_set_output_format(prn, ISL_FORMAT_EXT_POLYLIB); 132 | prn = Func(prn, t); 133 | char *str = isl_printer_get_str(prn); 134 | char *oslStr = new char[strlen(str) + 11]; 135 | char *oslStrKeeper = oslStr; // osl_relation_sread advances the pointer... 136 | sprintf(oslStr, "UNDEFINED\n%s", str); 137 | osl_relation_p relation = osl_relation_sread(&oslStr); // TODO: add osl_relation_sread_polylib to facilitate this 138 | delete [] oslStrKeeper; 139 | free(str); 140 | isl_printer_free(prn); 141 | return relation; 142 | } 143 | 144 | template 145 | static T *osl2isl(T *(&Func)(isl_ctx *, const char *), osl_relation_p relation, osl_names_p names = nullptr) { 146 | CLINT_ASSERT(relation != nullptr, "Relation pointer is null"); 147 | 148 | char *string = osl_relation_spprint_polylib(relation, NULL); 149 | T *t = Func(m_islContext, string); 150 | free(string); 151 | return t; 152 | } 153 | }; 154 | 155 | #endif // ENUMERATOR_H 156 | -------------------------------------------------------------------------------- /examples/diagonal.c: -------------------------------------------------------------------------------- 1 | #pragma scop 2 | for (int i = 0; i < 2; i++) { 3 | for (int j = i; j < i+1; j++) { 4 | S(i, j); 5 | } 6 | } 7 | 8 | for (int i = 3; i < 42; i++) { 9 | for (int j = i; j < i+1; j++) { 10 | S(i, j); 11 | } 12 | } 13 | #pragma endscop 14 | -------------------------------------------------------------------------------- /examples/diagonal.scop: -------------------------------------------------------------------------------- 1 | # 2 | # <| 3 | # A 4 | # /.\ 5 | # <| [""M# 6 | # A | # Clan McCloog Castle 7 | # /.\ [""M# [Generated by Clan 0.8.0] 8 | # [""M# | # U"U#U 9 | # | # | # \ .:/ 10 | # | # | #___| # 11 | # | "--' .-" 12 | # |"-"-"-"-"-#-#-## 13 | # | # ## ###### 14 | # \ .::::'/ 15 | # \ ::::'/ 16 | # :8a| # # ## 17 | # ::88a ### 18 | # ::::888a 8a ##::. 19 | # ::::::888a88a[]:::: 20 | # :::::::::SUNDOGa8a::::. .. 21 | # :::::8::::888:Y8888:::::::::... 22 | #::':::88::::888::Y88a______________________________________________________ 23 | #:: ::::88a::::88a:Y88a __---__-- __ 24 | #' .: ::Y88a:::::8a:Y88a __----_-- -------_-__ 25 | # :' ::::8P::::::::::88aa. _ _- -- --_ --- __ --- __-- 26 | #.:: :::::::::::::::::::Y88as88a...s88aa. 27 | # 28 | # [File generated by the OpenScop Library 0.9.0] 29 | 30 | 31 | 32 | # =============================================== Global 33 | # Language 34 | C 35 | 36 | # Context 37 | CONTEXT 38 | 0 2 0 0 0 0 39 | 40 | # Parameters are not provided 41 | 0 42 | 43 | 44 | # Number of statements 45 | 2 46 | 47 | # =============================================== Statement 1 48 | # Number of relations describing the statement: 49 | 4 50 | 51 | # ---------------------------------------------- 1.1 Domain 52 | DOMAIN 53 | 4 4 2 0 0 0 54 | # e/i| i j | 1 55 | 1 1 0 0 ## i >= 0 56 | 1 -1 0 1 ## -i+1 >= 0 57 | 1 -1 1 0 ## -i+j >= 0 58 | 1 1 -1 0 ## i-j >= 0 59 | 60 | # ---------------------------------------------- 1.2 Scattering 61 | SCATTERING 62 | 5 9 5 2 0 0 63 | # e/i| c1 c2 c3 c4 c5 | i j | 1 64 | 0 -1 0 0 0 0 0 0 0 ## c1 == 0 65 | 0 0 -1 0 0 0 1 0 0 ## c2 == i 66 | 0 0 0 -1 0 0 0 0 0 ## c3 == 0 67 | 0 0 0 0 -1 0 0 1 0 ## c4 == j 68 | 0 0 0 0 0 -1 0 0 0 ## c5 == 0 69 | 70 | # ---------------------------------------------- 1.3 Access 71 | READ 72 | 1 5 1 2 0 0 73 | # e/i| Arr| i j | 1 74 | 0 -1 0 0 1 ## Arr == i 75 | 76 | READ 77 | 1 5 1 2 0 0 78 | # e/i| Arr| i j | 1 79 | 0 -1 0 0 2 ## Arr == j 80 | 81 | # ---------------------------------------------- 1.4 Statement Extensions 82 | # Number of Statement Extensions 83 | 1 84 | 85 | # Number of original iterators 86 | 2 87 | # List of original iterators 88 | i j 89 | # Statement body expression 90 | S(i, j); 91 | 92 | 93 | # =============================================== Statement 2 94 | # Number of relations describing the statement: 95 | 4 96 | 97 | # ---------------------------------------------- 2.1 Domain 98 | DOMAIN 99 | 4 4 2 0 0 0 100 | # e/i| i j | 1 101 | 1 1 0 -3 ## i-3 >= 0 102 | 1 -1 0 41 ## -i+41 >= 0 103 | 1 -1 1 0 ## -i+j >= 0 104 | 1 1 -1 0 ## i-j >= 0 105 | 106 | # ---------------------------------------------- 2.2 Scattering 107 | SCATTERING 108 | 5 9 5 2 0 0 109 | # e/i| c1 c2 c3 c4 c5 | i j | 1 110 | 0 -1 0 0 0 0 0 0 1 ## c1 == 1 111 | 0 0 -1 0 0 0 1 0 0 ## c2 == i 112 | 0 0 0 -1 0 0 0 0 0 ## c3 == 0 113 | 0 0 0 0 -1 0 0 1 0 ## c4 == j 114 | 0 0 0 0 0 -1 0 0 0 ## c5 == 0 115 | 116 | # ---------------------------------------------- 2.3 Access 117 | READ 118 | 1 5 1 2 0 0 119 | # e/i| Arr| i j | 1 120 | 0 -1 0 0 1 ## Arr == i 121 | 122 | READ 123 | 1 5 1 2 0 0 124 | # e/i| Arr| i j | 1 125 | 0 -1 0 0 2 ## Arr == j 126 | 127 | # ---------------------------------------------- 2.4 Statement Extensions 128 | # Number of Statement Extensions 129 | 1 130 | 131 | # Number of original iterators 132 | 2 133 | # List of original iterators 134 | i j 135 | # Statement body expression 136 | S(i, j); 137 | 138 | 139 | # =============================================== Extensions 140 | 141 | b0 i b1 j b2 142 | 143 | 144 | 145 | # Number of arrays 146 | 3 147 | # Mapping array-identifiers/array-names 148 | 1 i 149 | 2 j 150 | 3 S 151 | 152 | 153 | 154 | # File name 155 | diagonal.c 156 | # Starting line and column 157 | 2 0 158 | # Ending line and column 159 | 13 0 160 | # Indentation 161 | 0 162 | 163 | 164 | 165 | 166 | -------------------------------------------------------------------------------- /examples/localdim.c: -------------------------------------------------------------------------------- 1 | #pragma scop 2 | for (int i = 0; i < N; i += 2) 3 | for (int j = 0; j < N; j++) 4 | S1(i, j); 5 | 6 | for (int i = 0; i < N; i++) 7 | for (int j = 0; j < N; j += 2) 8 | S2(i, j); 9 | 10 | for (int i = 0; i < N; i += 2) 11 | for (int j = 0; j < N; j += 2) 12 | S3(i, j); 13 | 14 | for (int i = 0; i < N; i++) 15 | for (int j = 0; j < N; j++) 16 | if ((i + j) % 2 == 0) 17 | S4(i, j); 18 | #pragma endscop 19 | -------------------------------------------------------------------------------- /examples/localdim.scop: -------------------------------------------------------------------------------- 1 | # 2 | # <| 3 | # A 4 | # /.\ 5 | # <| [""M# 6 | # A | # Clan McCloog Castle 7 | # /.\ [""M# [Generated by Clan 0.8.0] 8 | # [""M# | # U"U#U 9 | # | # | # \ .:/ 10 | # | # | #___| # 11 | # | "--' .-" 12 | # |"-"-"-"-"-#-#-## 13 | # | # ## ###### 14 | # \ .::::'/ 15 | # \ ::::'/ 16 | # :8a| # # ## 17 | # ::88a ### 18 | # ::::888a 8a ##::. 19 | # ::::::888a88a[]:::: 20 | # :::::::::SUNDOGa8a::::. .. 21 | # :::::8::::888:Y8888:::::::::... 22 | #::':::88::::888::Y88a______________________________________________________ 23 | #:: ::::88a::::88a:Y88a __---__-- __ 24 | #' .: ::Y88a:::::8a:Y88a __----_-- -------_-__ 25 | # :' ::::8P::::::::::88aa. _ _- -- --_ --- __ --- __-- 26 | #.:: :::::::::::::::::::Y88as88a...s88aa. 27 | # 28 | # [File generated by the OpenScop Library 0.9.0] 29 | 30 | 31 | 32 | # =============================================== Global 33 | # Language 34 | C 35 | 36 | # Context 37 | CONTEXT 38 | 0 3 0 0 0 1 39 | 40 | # Parameters are provided 41 | 1 42 | 43 | N 44 | 45 | 46 | # Number of statements 47 | 4 48 | 49 | # =============================================== Statement 1 50 | # Number of relations describing the statement: 51 | 4 52 | 53 | # ---------------------------------------------- 1.1 Domain 54 | DOMAIN# {{{ 55 | 6 6 2 0 1 1 56 | # e/i| i j | l1 | N | 1 57 | 1 -1 0 0 1 -1 ## -i+N-1 >= 0 58 | 1 0 0 0 1 -1 ## N-1 >= 0 59 | 1 1 0 0 0 0 ## i >= 0 60 | 0 -1 0 2 0 0 ## i == 2*l1 61 | 1 0 1 0 0 0 ## j >= 0 62 | 1 0 -1 0 1 -1 ## -j+N-1 >= 0# }}} 63 | 64 | # ---------------------------------------------- 1.2 Scattering 65 | SCATTERING 66 | 5 10 5 2 0 1 67 | # e/i| c1 c2 c3 c4 c5 | i j | N | 1 68 | 0 -1 0 0 0 0 0 0 0 0 ## c1 == 0 69 | 0 0 -1 0 0 0 1 0 0 0 ## c2 == i 70 | 0 0 0 -1 0 0 0 0 0 0 ## c3 == 0 71 | 0 0 0 0 -1 0 0 1 0 0 ## c4 == j 72 | 0 0 0 0 0 -1 0 0 0 0 ## c5 == 0 73 | 74 | # ---------------------------------------------- 1.3 Access 75 | READ 76 | 1 6 1 2 0 1 77 | # e/i| Arr| i j | N | 1 78 | 0 -1 0 0 0 1 ## Arr == i 79 | 80 | READ 81 | 1 6 1 2 0 1 82 | # e/i| Arr| i j | N | 1 83 | 0 -1 0 0 0 3 ## Arr == j 84 | 85 | # ---------------------------------------------- 1.4 Statement Extensions 86 | # Number of Statement Extensions 87 | 1 88 | 89 | # Number of original iterators 90 | 2 91 | # List of original iterators 92 | i j 93 | # Statement body expression 94 | S1(i, j); 95 | 96 | 97 | # =============================================== Statement 2 98 | # Number of relations describing the statement: 99 | 4 100 | 101 | # ---------------------------------------------- 2.1 Domain 102 | DOMAIN 103 | 6 6 2 0 1 1 104 | # e/i| i j | l1 | N | 1 105 | 1 1 0 0 0 0 ## i >= 0 106 | 1 -1 0 0 1 -1 ## -i+N-1 >= 0 107 | 1 0 0 0 1 -1 ## N-1 >= 0 108 | 1 0 -1 0 1 -1 ## -j+N-1 >= 0 109 | 1 0 1 0 0 0 ## j >= 0 110 | 0 0 -1 2 0 0 ## j == 2*l1 111 | 112 | # ---------------------------------------------- 2.2 Scattering 113 | SCATTERING 114 | 5 10 5 2 0 1 115 | # e/i| c1 c2 c3 c4 c5 | i j | N | 1 116 | 0 -1 0 0 0 0 0 0 0 1 ## c1 == 1 117 | 0 0 -1 0 0 0 1 0 0 0 ## c2 == i 118 | 0 0 0 -1 0 0 0 0 0 0 ## c3 == 0 119 | 0 0 0 0 -1 0 0 1 0 0 ## c4 == j 120 | 0 0 0 0 0 -1 0 0 0 0 ## c5 == 0 121 | 122 | # ---------------------------------------------- 2.3 Access 123 | READ 124 | 1 6 1 2 0 1 125 | # e/i| Arr| i j | N | 1 126 | 0 -1 0 0 0 1 ## Arr == i 127 | 128 | READ 129 | 1 6 1 2 0 1 130 | # e/i| Arr| i j | N | 1 131 | 0 -1 0 0 0 3 ## Arr == j 132 | 133 | # ---------------------------------------------- 2.4 Statement Extensions 134 | # Number of Statement Extensions 135 | 1 136 | 137 | # Number of original iterators 138 | 2 139 | # List of original iterators 140 | i j 141 | # Statement body expression 142 | S2(i, j); 143 | 144 | 145 | # =============================================== Statement 3 146 | # Number of relations describing the statement: 147 | 4 148 | 149 | # ---------------------------------------------- 3.1 Domain 150 | DOMAIN 151 | 7 8 2 0 3 1 152 | # e/i| i j | l1 l2 l3 | N | 1 153 | 1 -1 0 0 0 0 1 -1 ## -i+N-1 >= 0 154 | 1 0 0 0 0 0 1 -1 ## N-1 >= 0 155 | 1 1 0 0 0 0 0 0 ## i >= 0 156 | 0 -1 0 2 0 0 0 0 ## i == 2*l1 157 | 1 0 -1 0 0 0 1 -1 ## -j+N-1 >= 0 158 | 1 0 1 0 0 0 0 0 ## j >= 0 159 | 0 0 -1 0 0 2 0 0 ## j == 2*l3 160 | 161 | # ---------------------------------------------- 3.2 Scattering 162 | SCATTERING 163 | 5 10 5 2 0 1 164 | # e/i| c1 c2 c3 c4 c5 | i j | N | 1 165 | 0 -1 0 0 0 0 0 0 0 2 ## c1 == 2 166 | 0 0 -1 0 0 0 1 0 0 0 ## c2 == i 167 | 0 0 0 -1 0 0 0 0 0 0 ## c3 == 0 168 | 0 0 0 0 -1 0 0 1 0 0 ## c4 == j 169 | 0 0 0 0 0 -1 0 0 0 0 ## c5 == 0 170 | 171 | # ---------------------------------------------- 3.3 Access 172 | READ 173 | 1 6 1 2 0 1 174 | # e/i| Arr| i j | N | 1 175 | 0 -1 0 0 0 1 ## Arr == i 176 | 177 | READ 178 | 1 6 1 2 0 1 179 | # e/i| Arr| i j | N | 1 180 | 0 -1 0 0 0 3 ## Arr == j 181 | 182 | # ---------------------------------------------- 3.4 Statement Extensions 183 | # Number of Statement Extensions 184 | 1 185 | 186 | # Number of original iterators 187 | 2 188 | # List of original iterators 189 | i j 190 | # Statement body expression 191 | S3(i, j); 192 | 193 | 194 | # =============================================== Statement 4 195 | # Number of relations describing the statement: 196 | 4 197 | 198 | # ---------------------------------------------- 4.1 Domain 199 | DOMAIN 200 | 6 8 2 0 3 1 201 | # e/i| i j | l1 l2 l3 | N | 1 202 | 1 1 0 0 0 0 0 0 ## i >= 0 203 | 1 -1 0 0 0 0 1 -1 ## -i+N-1 >= 0 204 | 1 0 0 0 0 0 1 -1 ## N-1 >= 0 205 | 1 0 1 0 0 0 0 0 ## j >= 0 206 | 1 0 -1 0 0 0 1 -1 ## -j+N-1 >= 0 207 | 0 1 1 0 0 -2 0 0 ## i+j-2*l3 == 0 208 | 209 | # ---------------------------------------------- 4.2 Scattering 210 | SCATTERING 211 | 5 10 5 2 0 1 212 | # e/i| c1 c2 c3 c4 c5 | i j | N | 1 213 | 0 -1 0 0 0 0 0 0 0 3 ## c1 == 3 214 | 0 0 -1 0 0 0 1 0 0 0 ## c2 == i 215 | 0 0 0 -1 0 0 0 0 0 0 ## c3 == 0 216 | 0 0 0 0 -1 0 0 1 0 0 ## c4 == j 217 | 0 0 0 0 0 -1 0 0 0 0 ## c5 == 0 218 | 219 | # ---------------------------------------------- 4.3 Access 220 | READ 221 | 1 6 1 2 0 1 222 | # e/i| Arr| i j | N | 1 223 | 0 -1 0 0 0 1 ## Arr == i 224 | 225 | READ 226 | 1 6 1 2 0 1 227 | # e/i| Arr| i j | N | 1 228 | 0 -1 0 0 0 3 ## Arr == j 229 | 230 | # ---------------------------------------------- 4.4 Statement Extensions 231 | # Number of Statement Extensions 232 | 1 233 | 234 | # Number of original iterators 235 | 2 236 | # List of original iterators 237 | i j 238 | # Statement body expression 239 | S4(i, j); 240 | 241 | 242 | # =============================================== Extensions 243 | 244 | b0 i b1 j b2 245 | 246 | 247 | 248 | # Number of arrays 249 | 7 250 | # Mapping array-identifiers/array-names 251 | 1 i 252 | 2 N 253 | 3 j 254 | 4 S1 255 | 5 S2 256 | 6 S3 257 | 7 S4 258 | 259 | 260 | 261 | # File name 262 | localdim.c 263 | # Starting line and column 264 | 2 0 265 | # Ending line and column 266 | 18 0 267 | # Indentation 268 | 0 269 | 270 | 271 | 272 | 273 | -------------------------------------------------------------------------------- /examples/localdimsched.c: -------------------------------------------------------------------------------- 1 | // IMPORTANT: The .scop file WAS MODIFIED from the one generated from this code 2 | #pragma scop 3 | for (int i = 0; i < N; i++) 4 | for (int j = 0; j < N; j++) 5 | S1(i, j); 6 | #pragma endscop 7 | -------------------------------------------------------------------------------- /examples/localdimsched.scop: -------------------------------------------------------------------------------- 1 | # 2 | # <| 3 | # A 4 | # /.\ 5 | # <| [""M# 6 | # A | # Clan McCloog Castle 7 | # /.\ [""M# [Generated by Clan 0.8.0] 8 | # [""M# | # U"U#U 9 | # | # | # \ .:/ 10 | # | # | #___| # 11 | # | "--' .-" 12 | # |"-"-"-"-"-#-#-## 13 | # | # ## ###### 14 | # \ .::::'/ 15 | # \ ::::'/ 16 | # :8a| # # ## 17 | # ::88a ### 18 | # ::::888a 8a ##::. 19 | # ::::::888a88a[]:::: 20 | # :::::::::SUNDOGa8a::::. .. 21 | # :::::8::::888:Y8888:::::::::... 22 | #::':::88::::888::Y88a______________________________________________________ 23 | #:: ::::88a::::88a:Y88a __---__-- __ 24 | #' .: ::Y88a:::::8a:Y88a __----_-- -------_-__ 25 | # :' ::::8P::::::::::88aa. _ _- -- --_ --- __ --- __-- 26 | #.:: :::::::::::::::::::Y88as88a...s88aa. 27 | # 28 | # [File generated by the OpenScop Library 0.9.0] 29 | 30 | 31 | 32 | # =============================================== Global 33 | # Language 34 | C 35 | 36 | # Context 37 | CONTEXT 38 | 0 3 0 0 0 1 39 | 40 | # Parameters are provided 41 | 1 42 | 43 | N 44 | 45 | 46 | # Number of statements 47 | 1 48 | 49 | # =============================================== Statement 1 50 | # Number of relations describing the statement: 51 | 4 52 | 53 | # ---------------------------------------------- 1.1 Domain 54 | DOMAIN 55 | 5 5 2 0 0 1 56 | # e/i| i j | N | 1 57 | 1 1 0 0 0 ## i >= 0 58 | 1 -1 0 1 -1 ## -i+N-1 >= 0 59 | 1 0 0 1 -1 ## N-1 >= 0 60 | 1 0 1 0 0 ## j >= 0 61 | 1 0 -1 1 -1 ## -j+N-1 >= 0 62 | 63 | # ---------------------------------------------- 1.2 Scattering 64 | SCATTERING 65 | 6 11 5 2 1 1 66 | # e/i| c1 c2 c3 c4 c5 | i j | l1 | N | 1 67 | 0 -1 0 0 0 0 0 0 0 0 0 ## c1 == 0 68 | 0 0 -1 0 0 0 2 0 0 0 0 ## c2 == i 69 | 0 0 0 -1 0 0 0 0 0 0 0 ## c3 == 0 70 | 0 0 0 0 -1 0 0 1 0 0 0 ## c4 == j 71 | 0 0 0 0 0 -1 0 0 0 0 0 ## c5 == 0 72 | 0 0 -1 0 0 0 0 0 2 0 0 ## c2 == 2*l1 73 | 74 | # ---------------------------------------------- 1.3 Access 75 | READ 76 | 1 6 1 2 0 1 77 | # e/i| Arr| i j | N | 1 78 | 0 -1 0 0 0 1 ## Arr == i 79 | 80 | READ 81 | 1 6 1 2 0 1 82 | # e/i| Arr| i j | N | 1 83 | 0 -1 0 0 0 3 ## Arr == j 84 | 85 | # ---------------------------------------------- 1.4 Statement Extensions 86 | # Number of Statement Extensions 87 | 1 88 | 89 | # Number of original iterators 90 | 2 91 | # List of original iterators 92 | i j 93 | # Statement body expression 94 | S1(i, j); 95 | 96 | 97 | # =============================================== Extensions 98 | 99 | b0 i b1 j b2 100 | 101 | 102 | 103 | # Number of arrays 104 | 4 105 | # Mapping array-identifiers/array-names 106 | 1 i 107 | 2 N 108 | 3 j 109 | 4 S1 110 | 111 | 112 | 113 | # File name 114 | localdimsched.c 115 | # Starting line and column 116 | 2 0 117 | # Ending line and column 118 | 5 0 119 | # Indentation 120 | 0 121 | 122 | 123 | 124 | 125 | -------------------------------------------------------------------------------- /examples/maxviz.c: -------------------------------------------------------------------------------- 1 | #pragma scop 2 | for (i1 = 0; i1 < N1; i1++) { 3 | for (j11 = 0; j11 < N2; j11++) { 4 | S1(i1, j11); 5 | S2(i1, j11); 6 | S3(i1, j11); 7 | } 8 | S4(i1); 9 | S5(i1); 10 | for (j12 = 0; j12 < N3; j12++) { 11 | S6(i1, j12); 12 | } 13 | for (j13 = 0; j13 < N4; j13++) { 14 | S7(i1, j13); 15 | S8(i1, j13); 16 | } 17 | } 18 | S9; 19 | S10; 20 | for (i2 = 0; i2 < N5; i2++) { 21 | for (j21 = 0; j21 < N6; j21++) { 22 | S11(i2, j21); 23 | } 24 | } 25 | for (i3 = 0; i3 < N7; i3++) { 26 | for (j31 = 0; j31 < N8; j31++) { 27 | S12(i3, j31); 28 | S13(i3, j31); 29 | } 30 | for (j32 = 0; j32 < N9; j32++) { 31 | S14(i3, j32); 32 | } 33 | } 34 | for (i4 = 0; i4 < N10; i++) { 35 | S15(i4); 36 | S16(i4); 37 | } 38 | #pragma endscop 39 | -------------------------------------------------------------------------------- /examples/next.c: -------------------------------------------------------------------------------- 1 | #pragma scop 2 | for (int i = 0; i < 16; i++) { 3 | for (int j = 0; j < 11; j++) { 4 | if (i < 1) 5 | S1(i, j); 6 | else if (i < 3) 7 | S2(i, j); 8 | else if (i < 7) 9 | S3(i, j); 10 | else if (i < 15) 11 | S4(i, j); 12 | } 13 | } 14 | #pragma endscop 15 | -------------------------------------------------------------------------------- /examples/next.scop: -------------------------------------------------------------------------------- 1 | # 2 | # <| 3 | # A 4 | # /.\ 5 | # <| [""M# 6 | # A | # Clan McCloog Castle 7 | # /.\ [""M# [Generated by Clan 0.8.0] 8 | # [""M# | # U"U#U 9 | # | # | # \ .:/ 10 | # | # | #___| # 11 | # | "--' .-" 12 | # |"-"-"-"-"-#-#-## 13 | # | # ## ###### 14 | # \ .::::'/ 15 | # \ ::::'/ 16 | # :8a| # # ## 17 | # ::88a ### 18 | # ::::888a 8a ##::. 19 | # ::::::888a88a[]:::: 20 | # :::::::::SUNDOGa8a::::. .. 21 | # :::::8::::888:Y8888:::::::::... 22 | #::':::88::::888::Y88a______________________________________________________ 23 | #:: ::::88a::::88a:Y88a __---__-- __ 24 | #' .: ::Y88a:::::8a:Y88a __----_-- -------_-__ 25 | # :' ::::8P::::::::::88aa. _ _- -- --_ --- __ --- __-- 26 | #.:: :::::::::::::::::::Y88as88a...s88aa. 27 | # 28 | # [File generated by the OpenScop Library 0.9.0] 29 | 30 | 31 | 32 | # =============================================== Global 33 | # Language 34 | C 35 | 36 | # Context 37 | CONTEXT 38 | 0 2 0 0 0 0 39 | 40 | # Parameters are not provided 41 | 0 42 | 43 | 44 | # Number of statements 45 | 4 46 | 47 | # =============================================== Statement 1 48 | # Number of relations describing the statement: 49 | 4 50 | 51 | # ---------------------------------------------- 1.1 Domain 52 | DOMAIN 53 | 5 4 2 0 0 0 54 | # e/i| i j | 1 55 | 1 1 0 0 ## i >= 0 56 | 1 -1 0 15 ## -i+15 >= 0 57 | 1 0 1 0 ## j >= 0 58 | 1 0 -1 10 ## -j+10 >= 0 59 | 1 -1 0 0 ## -i >= 0 60 | 61 | # ---------------------------------------------- 1.2 Scattering 62 | SCATTERING 63 | 5 9 5 2 0 0 64 | # e/i| c1 c2 c3 c4 c5 | i j | 1 65 | 0 -1 0 0 0 0 0 0 0 ## c1 == 0 66 | 0 0 -1 0 0 0 1 0 0 ## c2 == i 67 | 0 0 0 -1 0 0 0 0 0 ## c3 == 0 68 | 0 0 0 0 -1 0 0 1 0 ## c4 == j 69 | 0 0 0 0 0 -1 0 0 0 ## c5 == 0 70 | 71 | # ---------------------------------------------- 1.3 Access 72 | READ 73 | 1 5 1 2 0 0 74 | # e/i| Arr| i j | 1 75 | 0 -1 0 0 1 ## Arr == i 76 | 77 | READ 78 | 1 5 1 2 0 0 79 | # e/i| Arr| i j | 1 80 | 0 -1 0 0 2 ## Arr == j 81 | 82 | # ---------------------------------------------- 1.4 Statement Extensions 83 | # Number of Statement Extensions 84 | 1 85 | 86 | # Number of original iterators 87 | 2 88 | # List of original iterators 89 | i j 90 | # Statement body expression 91 | S1(i, j); 92 | 93 | 94 | # =============================================== Statement 2 95 | # Number of relations describing the statement: 96 | 4 97 | 98 | # ---------------------------------------------- 2.1 Domain 99 | DOMAIN 100 | 6 4 2 0 0 0 101 | # e/i| i j | 1 102 | 1 1 0 0 ## i >= 0 103 | 1 -1 0 15 ## -i+15 >= 0 104 | 1 0 1 0 ## j >= 0 105 | 1 0 -1 10 ## -j+10 >= 0 106 | 1 1 0 -1 ## i-1 >= 0 107 | 1 -1 0 2 ## -i+2 >= 0 108 | 109 | # ---------------------------------------------- 2.2 Scattering 110 | SCATTERING 111 | 5 9 5 2 0 0 112 | # e/i| c1 c2 c3 c4 c5 | i j | 1 113 | 0 -1 0 0 0 0 0 0 0 ## c1 == 0 114 | 0 0 -1 0 0 0 1 0 0 ## c2 == i 115 | 0 0 0 -1 0 0 0 0 0 ## c3 == 0 116 | 0 0 0 0 -1 0 0 1 0 ## c4 == j 117 | 0 0 0 0 0 -1 0 0 1 ## c5 == 1 118 | 119 | # ---------------------------------------------- 2.3 Access 120 | READ 121 | 1 5 1 2 0 0 122 | # e/i| Arr| i j | 1 123 | 0 -1 0 0 1 ## Arr == i 124 | 125 | READ 126 | 1 5 1 2 0 0 127 | # e/i| Arr| i j | 1 128 | 0 -1 0 0 2 ## Arr == j 129 | 130 | # ---------------------------------------------- 2.4 Statement Extensions 131 | # Number of Statement Extensions 132 | 1 133 | 134 | # Number of original iterators 135 | 2 136 | # List of original iterators 137 | i j 138 | # Statement body expression 139 | S2(i, j); 140 | 141 | 142 | # =============================================== Statement 3 143 | # Number of relations describing the statement: 144 | 4 145 | 146 | # ---------------------------------------------- 3.1 Domain 147 | DOMAIN 148 | 7 4 2 0 0 0 149 | # e/i| i j | 1 150 | 1 1 0 0 ## i >= 0 151 | 1 -1 0 15 ## -i+15 >= 0 152 | 1 0 1 0 ## j >= 0 153 | 1 0 -1 10 ## -j+10 >= 0 154 | 1 1 0 -1 ## i-1 >= 0 155 | 1 1 0 -3 ## i-3 >= 0 156 | 1 -1 0 6 ## -i+6 >= 0 157 | 158 | # ---------------------------------------------- 3.2 Scattering 159 | SCATTERING 160 | 5 9 5 2 0 0 161 | # e/i| c1 c2 c3 c4 c5 | i j | 1 162 | 0 -1 0 0 0 0 0 0 0 ## c1 == 0 163 | 0 0 -1 0 0 0 1 0 0 ## c2 == i 164 | 0 0 0 -1 0 0 0 0 0 ## c3 == 0 165 | 0 0 0 0 -1 0 0 1 0 ## c4 == j 166 | 0 0 0 0 0 -1 0 0 2 ## c5 == 2 167 | 168 | # ---------------------------------------------- 3.3 Access 169 | READ 170 | 1 5 1 2 0 0 171 | # e/i| Arr| i j | 1 172 | 0 -1 0 0 1 ## Arr == i 173 | 174 | READ 175 | 1 5 1 2 0 0 176 | # e/i| Arr| i j | 1 177 | 0 -1 0 0 2 ## Arr == j 178 | 179 | # ---------------------------------------------- 3.4 Statement Extensions 180 | # Number of Statement Extensions 181 | 1 182 | 183 | # Number of original iterators 184 | 2 185 | # List of original iterators 186 | i j 187 | # Statement body expression 188 | S3(i, j); 189 | 190 | 191 | # =============================================== Statement 4 192 | # Number of relations describing the statement: 193 | 4 194 | 195 | # ---------------------------------------------- 4.1 Domain 196 | DOMAIN 197 | 8 4 2 0 0 0 198 | # e/i| i j | 1 199 | 1 1 0 0 ## i >= 0 200 | 1 -1 0 15 ## -i+15 >= 0 201 | 1 0 1 0 ## j >= 0 202 | 1 0 -1 10 ## -j+10 >= 0 203 | 1 1 0 -1 ## i-1 >= 0 204 | 1 1 0 -3 ## i-3 >= 0 205 | 1 1 0 -7 ## i-7 >= 0 206 | 1 -1 0 14 ## -i+14 >= 0 207 | 208 | # ---------------------------------------------- 4.2 Scattering 209 | SCATTERING 210 | 5 9 5 2 0 0 211 | # e/i| c1 c2 c3 c4 c5 | i j | 1 212 | 0 -1 0 0 0 0 0 0 0 ## c1 == 0 213 | 0 0 -1 0 0 0 1 0 0 ## c2 == i 214 | 0 0 0 -1 0 0 0 0 0 ## c3 == 0 215 | 0 0 0 0 -1 0 0 1 0 ## c4 == j 216 | 0 0 0 0 0 -1 0 0 3 ## c5 == 3 217 | 218 | # ---------------------------------------------- 4.3 Access 219 | READ 220 | 1 5 1 2 0 0 221 | # e/i| Arr| i j | 1 222 | 0 -1 0 0 1 ## Arr == i 223 | 224 | READ 225 | 1 5 1 2 0 0 226 | # e/i| Arr| i j | 1 227 | 0 -1 0 0 2 ## Arr == j 228 | 229 | # ---------------------------------------------- 4.4 Statement Extensions 230 | # Number of Statement Extensions 231 | 1 232 | 233 | # Number of original iterators 234 | 2 235 | # List of original iterators 236 | i j 237 | # Statement body expression 238 | S4(i, j); 239 | 240 | 241 | # =============================================== Extensions 242 | 243 | b0 i b1 j b2 244 | 245 | 246 | 247 | # Number of arrays 248 | 6 249 | # Mapping array-identifiers/array-names 250 | 1 i 251 | 2 j 252 | 3 S1 253 | 4 S2 254 | 5 S3 255 | 6 S4 256 | 257 | 258 | 259 | # File name 260 | next.c 261 | # Starting line and column 262 | 2 0 263 | # Ending line and column 264 | 14 0 265 | # Indentation 266 | 0 267 | 268 | 269 | 270 | 271 | -------------------------------------------------------------------------------- /examples/onedim.c: -------------------------------------------------------------------------------- 1 | #pragma scop 2 | for (int i = 0; i < 42; i++) 3 | S(i); 4 | for (int i = 0; i < 1; i++) 5 | for (int j = 0; j < 42; j++) 6 | S(i, j); 7 | #pragma endscop 8 | -------------------------------------------------------------------------------- /examples/onedim.scop: -------------------------------------------------------------------------------- 1 | # 2 | # <| 3 | # A 4 | # /.\ 5 | # <| [""M# 6 | # A | # Clan McCloog Castle 7 | # /.\ [""M# [Generated by Clan 0.8.0] 8 | # [""M# | # U"U#U 9 | # | # | # \ .:/ 10 | # | # | #___| # 11 | # | "--' .-" 12 | # |"-"-"-"-"-#-#-## 13 | # | # ## ###### 14 | # \ .::::'/ 15 | # \ ::::'/ 16 | # :8a| # # ## 17 | # ::88a ### 18 | # ::::888a 8a ##::. 19 | # ::::::888a88a[]:::: 20 | # :::::::::SUNDOGa8a::::. .. 21 | # :::::8::::888:Y8888:::::::::... 22 | #::':::88::::888::Y88a______________________________________________________ 23 | #:: ::::88a::::88a:Y88a __---__-- __ 24 | #' .: ::Y88a:::::8a:Y88a __----_-- -------_-__ 25 | # :' ::::8P::::::::::88aa. _ _- -- --_ --- __ --- __-- 26 | #.:: :::::::::::::::::::Y88as88a...s88aa. 27 | # 28 | # [File generated by the OpenScop Library 0.9.0] 29 | 30 | 31 | 32 | # =============================================== Global 33 | # Language 34 | C 35 | 36 | # Context 37 | CONTEXT 38 | 0 2 0 0 0 0 39 | 40 | # Parameters are not provided 41 | 0 42 | 43 | 44 | # Number of statements 45 | 2 46 | 47 | # =============================================== Statement 1 48 | # Number of relations describing the statement: 49 | 3 50 | 51 | # ---------------------------------------------- 1.1 Domain 52 | DOMAIN 53 | 2 3 1 0 0 0 54 | # e/i| i | 1 55 | 1 1 0 ## i >= 0 56 | 1 -1 41 ## -i+41 >= 0 57 | 58 | # ---------------------------------------------- 1.2 Scattering 59 | SCATTERING 60 | 3 6 3 1 0 0 61 | # e/i| c1 c2 c3 | i | 1 62 | 0 -1 0 0 0 0 ## c1 == 0 63 | 0 0 -1 0 1 0 ## c2 == i 64 | 0 0 0 -1 0 0 ## c3 == 0 65 | 66 | # ---------------------------------------------- 1.3 Access 67 | READ 68 | 1 4 1 1 0 0 69 | # e/i| Arr| i | 1 70 | 0 -1 0 1 ## Arr == i 71 | 72 | # ---------------------------------------------- 1.4 Statement Extensions 73 | # Number of Statement Extensions 74 | 1 75 | 76 | # Number of original iterators 77 | 1 78 | # List of original iterators 79 | i 80 | # Statement body expression 81 | S(i); 82 | 83 | 84 | # =============================================== Statement 2 85 | # Number of relations describing the statement: 86 | 4 87 | 88 | # ---------------------------------------------- 2.1 Domain 89 | DOMAIN 90 | 4 4 2 0 0 0 91 | # e/i| i j | 1 92 | 1 1 0 0 ## i >= 0 93 | 1 -1 0 0 ## -i >= 0 94 | 1 0 1 0 ## j >= 0 95 | 1 0 -1 41 ## -j+41 >= 0 96 | 97 | # ---------------------------------------------- 2.2 Scattering 98 | SCATTERING 99 | 5 9 5 2 0 0 100 | # e/i| c1 c2 c3 c4 c5 | i j | 1 101 | 0 -1 0 0 0 0 0 0 1 ## c1 == 1 102 | 0 0 -1 0 0 0 1 0 0 ## c2 == i 103 | 0 0 0 -1 0 0 0 0 0 ## c3 == 0 104 | 0 0 0 0 -1 0 0 1 0 ## c4 == j 105 | 0 0 0 0 0 -1 0 0 0 ## c5 == 0 106 | 107 | # ---------------------------------------------- 2.3 Access 108 | READ 109 | 1 5 1 2 0 0 110 | # e/i| Arr| i j | 1 111 | 0 -1 0 0 1 ## Arr == i 112 | 113 | READ 114 | 1 5 1 2 0 0 115 | # e/i| Arr| i j | 1 116 | 0 -1 0 0 3 ## Arr == j 117 | 118 | # ---------------------------------------------- 2.4 Statement Extensions 119 | # Number of Statement Extensions 120 | 1 121 | 122 | # Number of original iterators 123 | 2 124 | # List of original iterators 125 | i j 126 | # Statement body expression 127 | S(i, j); 128 | 129 | 130 | # =============================================== Extensions 131 | 132 | b0 i b1 j b2 133 | 134 | 135 | 136 | # Number of arrays 137 | 3 138 | # Mapping array-identifiers/array-names 139 | 1 i 140 | 2 S 141 | 3 j 142 | 143 | 144 | 145 | # File name 146 | onedim.c 147 | # Starting line and column 148 | 2 0 149 | # Ending line and column 150 | 7 0 151 | # Indentation 152 | 0 153 | 154 | 155 | 156 | 157 | -------------------------------------------------------------------------------- /examples/oneiter.c: -------------------------------------------------------------------------------- 1 | #pragma scop 2 | for (int i = 5; i < 6; i++) 3 | for (int j = 4; j < 5; j++) 4 | for (int k = 3; k < 4; k++) 5 | for (int l = 2; l < 3; l++) 6 | S(i, j); 7 | #pragma endscop 8 | -------------------------------------------------------------------------------- /examples/oneiter.scop: -------------------------------------------------------------------------------- 1 | # 2 | # <| 3 | # A 4 | # /.\ 5 | # <| [""M# 6 | # A | # Clan McCloog Castle 7 | # /.\ [""M# [Generated by Clan 0.8.0] 8 | # [""M# | # U"U#U 9 | # | # | # \ .:/ 10 | # | # | #___| # 11 | # | "--' .-" 12 | # |"-"-"-"-"-#-#-## 13 | # | # ## ###### 14 | # \ .::::'/ 15 | # \ ::::'/ 16 | # :8a| # # ## 17 | # ::88a ### 18 | # ::::888a 8a ##::. 19 | # ::::::888a88a[]:::: 20 | # :::::::::SUNDOGa8a::::. .. 21 | # :::::8::::888:Y8888:::::::::... 22 | #::':::88::::888::Y88a______________________________________________________ 23 | #:: ::::88a::::88a:Y88a __---__-- __ 24 | #' .: ::Y88a:::::8a:Y88a __----_-- -------_-__ 25 | # :' ::::8P::::::::::88aa. _ _- -- --_ --- __ --- __-- 26 | #.:: :::::::::::::::::::Y88as88a...s88aa. 27 | # 28 | # [File generated by the OpenScop Library 0.9.0] 29 | 30 | 31 | 32 | # =============================================== Global 33 | # Language 34 | C 35 | 36 | # Context 37 | CONTEXT 38 | 0 2 0 0 0 0 39 | 40 | # Parameters are not provided 41 | 0 42 | 43 | 44 | # Number of statements 45 | 1 46 | 47 | # =============================================== Statement 1 48 | # Number of relations describing the statement: 49 | 4 50 | 51 | # ---------------------------------------------- 1.1 Domain 52 | DOMAIN 53 | 8 6 4 0 0 0 54 | # e/i| i j k l | 1 55 | 1 1 0 0 0 -5 ## i-5 >= 0 56 | 1 -1 0 0 0 5 ## -i+5 >= 0 57 | 1 0 1 0 0 -4 ## j-4 >= 0 58 | 1 0 -1 0 0 4 ## -j+4 >= 0 59 | 1 0 0 1 0 -3 ## k-3 >= 0 60 | 1 0 0 -1 0 3 ## -k+3 >= 0 61 | 1 0 0 0 1 -2 ## l-2 >= 0 62 | 1 0 0 0 -1 2 ## -l+2 >= 0 63 | 64 | # ---------------------------------------------- 1.2 Scattering 65 | SCATTERING 66 | 9 15 9 4 0 0 67 | # e/i| c1 c2 c3 c4 c5 c6 c7 c8 c9 | i j k l | 1 68 | 0 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 ## c1 == 0 69 | 0 0 -1 0 0 0 0 0 0 0 1 0 0 0 0 ## c2 == i 70 | 0 0 0 -1 0 0 0 0 0 0 0 0 0 0 0 ## c3 == 0 71 | 0 0 0 0 -1 0 0 0 0 0 0 1 0 0 0 ## c4 == j 72 | 0 0 0 0 0 -1 0 0 0 0 0 0 0 0 0 ## c5 == 0 73 | 0 0 0 0 0 0 -1 0 0 0 0 0 1 0 0 ## c6 == k 74 | 0 0 0 0 0 0 0 -1 0 0 0 0 0 0 0 ## c7 == 0 75 | 0 0 0 0 0 0 0 0 -1 0 0 0 0 1 0 ## c8 == l 76 | 0 0 0 0 0 0 0 0 0 -1 0 0 0 0 0 ## c9 == 0 77 | 78 | # ---------------------------------------------- 1.3 Access 79 | READ 80 | 1 7 1 4 0 0 81 | # e/i| Arr| i j k l | 1 82 | 0 -1 0 0 0 0 1 ## Arr == i 83 | 84 | READ 85 | 1 7 1 4 0 0 86 | # e/i| Arr| i j k l | 1 87 | 0 -1 0 0 0 0 2 ## Arr == j 88 | 89 | # ---------------------------------------------- 1.4 Statement Extensions 90 | # Number of Statement Extensions 91 | 1 92 | 93 | # Number of original iterators 94 | 4 95 | # List of original iterators 96 | i j k l 97 | # Statement body expression 98 | S(i, j); 99 | 100 | 101 | # =============================================== Extensions 102 | 103 | b0 i b1 j b2 k b3 l b4 104 | 105 | 106 | 107 | # Number of arrays 108 | 5 109 | # Mapping array-identifiers/array-names 110 | 1 i 111 | 2 j 112 | 3 k 113 | 4 l 114 | 5 S 115 | 116 | 117 | 118 | # File name 119 | oneiter.c 120 | # Starting line and column 121 | 2 0 122 | # Ending line and column 123 | 7 0 124 | # Indentation 125 | 0 126 | 127 | 128 | 129 | 130 | -------------------------------------------------------------------------------- /examples/simple.c: -------------------------------------------------------------------------------- 1 | #pragma scop 2 | for (int i = 0; i < N; i++) 3 | for (int j = 0; j < N; j++) { 4 | A[i][j] = 0; 5 | } 6 | #pragma endscop 7 | -------------------------------------------------------------------------------- /examples/simple.scop: -------------------------------------------------------------------------------- 1 | # 2 | # <| 3 | # A 4 | # /.\ 5 | # <| [""M# 6 | # A | # Clan McCloog Castle 7 | # /.\ [""M# [Generated by Clan 0.8.0] 8 | # [""M# | # U"U#U 9 | # | # | # \ .:/ 10 | # | # | #___| # 11 | # | "--' .-" 12 | # |"-"-"-"-"-#-#-## 13 | # | # ## ###### 14 | # \ .::::'/ 15 | # \ ::::'/ 16 | # :8a| # # ## 17 | # ::88a ### 18 | # ::::888a 8a ##::. 19 | # ::::::888a88a[]:::: 20 | # :::::::::SUNDOGa8a::::. .. 21 | # :::::8::::888:Y8888:::::::::... 22 | #::':::88::::888::Y88a______________________________________________________ 23 | #:: ::::88a::::88a:Y88a __---__-- __ 24 | #' .: ::Y88a:::::8a:Y88a __----_-- -------_-__ 25 | # :' ::::8P::::::::::88aa. _ _- -- --_ --- __ --- __-- 26 | #.:: :::::::::::::::::::Y88as88a...s88aa. 27 | # 28 | # [File generated by the OpenScop Library 0.9.0] 29 | 30 | 31 | 32 | # =============================================== Global 33 | # Language 34 | C 35 | 36 | # Context 37 | CONTEXT 38 | 0 3 0 0 0 1 39 | 40 | # Parameters are provided 41 | 1 42 | 43 | N 44 | 45 | 46 | # Number of statements 47 | 1 48 | 49 | # =============================================== Statement 1 50 | # Number of relations describing the statement: 51 | 3 52 | 53 | # ---------------------------------------------- 1.1 Domain 54 | DOMAIN 55 | 5 5 2 0 0 1 56 | # e/i| i j | N | 1 57 | 1 1 0 0 0 ## i >= 0 58 | 1 -1 0 1 -1 ## -i+N-1 >= 0 59 | 1 0 0 1 -1 ## N-1 >= 0 60 | 1 0 1 0 0 ## j >= 0 61 | 1 0 -1 1 -1 ## -j+N-1 >= 0 62 | 63 | # ---------------------------------------------- 1.2 Scattering 64 | SCATTERING 65 | 5 10 5 2 0 1 66 | # e/i| c1 c2 c3 c4 c5 | i j | N | 1 67 | 0 -1 0 0 0 0 0 0 0 0 ## c1 == 0 68 | 0 0 -1 0 0 0 1 0 0 0 ## c2 == i 69 | 0 0 0 -1 0 0 0 0 0 0 ## c3 == 0 70 | 0 0 0 0 -1 0 0 1 0 0 ## c4 == j 71 | 0 0 0 0 0 -1 0 0 0 0 ## c5 == 0 72 | 73 | # ---------------------------------------------- 1.3 Access 74 | WRITE 75 | 3 8 3 2 0 1 76 | # e/i| Arr [1] [2]| i j | N | 1 77 | 0 -1 0 0 0 0 0 4 ## Arr == A 78 | 0 0 -1 0 1 0 0 0 ## [1] == i 79 | 0 0 0 -1 0 1 0 0 ## [2] == j 80 | 81 | # ---------------------------------------------- 1.4 Statement Extensions 82 | # Number of Statement Extensions 83 | 1 84 | 85 | # Number of original iterators 86 | 2 87 | # List of original iterators 88 | i j 89 | # Statement body expression 90 | A[i][j] = 0; 91 | 92 | 93 | # =============================================== Extensions 94 | 95 | b0 i b1 j b2 96 | 97 | 98 | 99 | # Number of arrays 100 | 4 101 | # Mapping array-identifiers/array-names 102 | 1 i 103 | 2 N 104 | 3 j 105 | 4 A 106 | 107 | 108 | 109 | # File name 110 | simple.c 111 | # Starting line and column 112 | 2 0 113 | # Ending line and column 114 | 6 0 115 | # Indentation 116 | 0 117 | 118 | 119 | 120 | 121 | -------------------------------------------------------------------------------- /examples/statement.c: -------------------------------------------------------------------------------- 1 | #pragma scop 2 | S; 3 | #pragma endscop 4 | -------------------------------------------------------------------------------- /examples/statement.scop: -------------------------------------------------------------------------------- 1 | # 2 | # <| 3 | # A 4 | # /.\ 5 | # <| [""M# 6 | # A | # Clan McCloog Castle 7 | # /.\ [""M# [Generated by Clan 0.8.0] 8 | # [""M# | # U"U#U 9 | # | # | # \ .:/ 10 | # | # | #___| # 11 | # | "--' .-" 12 | # |"-"-"-"-"-#-#-## 13 | # | # ## ###### 14 | # \ .::::'/ 15 | # \ ::::'/ 16 | # :8a| # # ## 17 | # ::88a ### 18 | # ::::888a 8a ##::. 19 | # ::::::888a88a[]:::: 20 | # :::::::::SUNDOGa8a::::. .. 21 | # :::::8::::888:Y8888:::::::::... 22 | #::':::88::::888::Y88a______________________________________________________ 23 | #:: ::::88a::::88a:Y88a __---__-- __ 24 | #' .: ::Y88a:::::8a:Y88a __----_-- -------_-__ 25 | # :' ::::8P::::::::::88aa. _ _- -- --_ --- __ --- __-- 26 | #.:: :::::::::::::::::::Y88as88a...s88aa. 27 | # 28 | # [File generated by the OpenScop Library 0.9.0] 29 | 30 | 31 | 32 | # =============================================== Global 33 | # Language 34 | C 35 | 36 | # Context 37 | CONTEXT 38 | 0 2 0 0 0 0 39 | 40 | # Parameters are not provided 41 | 0 42 | 43 | 44 | # Number of statements 45 | 1 46 | 47 | # =============================================== Statement 1 48 | # Number of relations describing the statement: 49 | 3 50 | 51 | # ---------------------------------------------- 1.1 Domain 52 | DOMAIN 53 | 0 2 0 0 0 0 54 | 55 | # ---------------------------------------------- 1.2 Scattering 56 | SCATTERING 57 | 1 3 1 0 0 0 58 | # e/i| c1 | 1 59 | 0 -1 0 ## c1 == 0 60 | 61 | # ---------------------------------------------- 1.3 Access 62 | READ 63 | 1 3 1 0 0 0 64 | # e/i| Arr| 1 65 | 0 -1 1 ## Arr == S 66 | 67 | # ---------------------------------------------- 1.4 Statement Extensions 68 | # Number of Statement Extensions 69 | 1 70 | 71 | # Number of original iterators 72 | 0 73 | # Statement body expression 74 | S; 75 | 76 | 77 | # =============================================== Extensions 78 | 79 | # Number of arrays 80 | 1 81 | # Mapping array-identifiers/array-names 82 | 1 S 83 | 84 | 85 | 86 | # File name 87 | statement.c 88 | # Starting line and column 89 | 2 0 90 | # Ending line and column 91 | 3 0 92 | # Indentation 93 | 0 94 | 95 | 96 | 97 | 98 | -------------------------------------------------------------------------------- /examples/triangles.c: -------------------------------------------------------------------------------- 1 | int main() { 2 | #pragma scop 3 | // |\ /| 4 | // | ) ( | 5 | // |/ \| 6 | for (int i = 0; i < 10; i++) { 7 | for (int j = i; j <= 10 - i; j++) { 8 | printf("%d, %d\n", i, j); 9 | } 10 | for (int j = 10 - i; j < i; j++) { 11 | printf("%d, %d\n", i, j); 12 | } 13 | } 14 | 15 | // ^ _____ 16 | // / \ \ / 17 | // /___\ \ / 18 | // v 19 | for (int i = 0; i <= 6; i++) { 20 | for (int j = 0; j <= 6; j++) { 21 | if (((i <= 3) && (j <= i)) || ((i > 3) && (j <= 6-i))) { 22 | printf("%d, %d\n", i, j); 23 | } 24 | } 25 | 26 | for (int j = 0; j <= 6; j++) { 27 | if (((i <= 3) && (j >= 6 - i)) || ((i > 3) && (j >= i))) { 28 | printf("%d, %d\n", i, j); 29 | } 30 | } 31 | } 32 | 33 | for (int i = 0; i <= 6; i++) { 34 | for (int j = 0; j <= i; j++) { 35 | printf("%d, %d\n", i, j); 36 | } 37 | for (int j = i; j <= 6; j++) { 38 | printf("%d, %d\n", i, j); 39 | } 40 | } 41 | 42 | for (int i = 0; i <= 6; i++) { 43 | for (int j = 0; j <= 6 - i; j++) { 44 | printf("%d, %d\n", i, j); 45 | } 46 | for (int j = 6 - i; j <= 6; j++) { 47 | printf("%d, %d\n", i, j); 48 | } 49 | } 50 | 51 | #pragma endscop 52 | } 53 | -------------------------------------------------------------------------------- /examples/unions.c: -------------------------------------------------------------------------------- 1 | // IMPORTANT: The .scop file WAS MODIFIED by calling Clay in this code 2 | #pragma scop 3 | /* Clay 4 | iss([0], {-1||2}); 5 | */ 6 | for (int i = 0; i < 10; i++) { 7 | if ((i <= 4) || (i >= 6)) { 8 | S[i] = S[i - 2]; 9 | } 10 | } 11 | #pragma endscop 12 | -------------------------------------------------------------------------------- /examples/unions.scop: -------------------------------------------------------------------------------- 1 | # [File generated by the OpenScop Library 0.9.0] 2 | 3 | 4 | 5 | # =============================================== Global 6 | # Language 7 | C 8 | 9 | # Context 10 | CONTEXT 11 | 0 2 0 0 0 0 12 | 13 | # Parameters are not provided 14 | 0 15 | 16 | 17 | # Number of statements 18 | 1 19 | 20 | # =============================================== Statement 1 21 | # Number of relations describing the statement: 22 | 4 23 | 24 | # ---------------------------------------------- 1.1 Domain 25 | DOMAIN 26 | # Union with 2 parts 27 | 2 28 | # Union part No.1 29 | 3 3 1 0 0 0 30 | # e/i| i | 1 31 | 1 1 0 ## i >= 0 32 | 1 -1 9 ## -i+9 >= 0 33 | 1 -1 4 ## -i+4 >= 0 34 | # Union part No.2 35 | 3 3 1 0 0 0 36 | # e/i| i | 1 37 | 1 1 0 ## i >= 0 38 | 1 -1 9 ## -i+9 >= 0 39 | 1 1 -6 ## i-6 >= 0 40 | 41 | # ---------------------------------------------- 1.2 Scattering 42 | SCATTERING 43 | # Union with 2 parts 44 | 2 45 | # Union part No.1 46 | 4 6 3 1 0 0 47 | # e/i| c1 c2 c3 | i | 1 48 | 0 -1 0 0 0 0 ## c1 == 0 49 | 0 0 -1 0 1 0 ## c2 == i 50 | 0 0 0 -1 0 1 ## c3 == 1 51 | 1 0 -1 0 0 2 ## -c2+2 >= 0 52 | # Union part No.2 53 | 4 6 3 1 0 0 54 | # e/i| c1 c2 c3 | i | 1 55 | 0 -1 0 0 0 0 ## c1 == 0 56 | 0 0 -1 0 1 0 ## c2 == i 57 | 0 0 0 -1 0 0 ## c3 == 0 58 | 1 0 1 0 0 -3 ## c2-3 >= 0 59 | 60 | # ---------------------------------------------- 1.3 Access 61 | WRITE 62 | 2 5 2 1 0 0 63 | # e/i| Arr [1]| i | 1 64 | 0 -1 0 0 2 ## Arr == S 65 | 0 0 -1 1 0 ## [1] == i 66 | 67 | READ 68 | 2 5 2 1 0 0 69 | # e/i| Arr [1]| i | 1 70 | 0 -1 0 0 2 ## Arr == S 71 | 0 0 -1 1 -2 ## [1] == i-2 72 | 73 | # ---------------------------------------------- 1.4 Statement Extensions 74 | # Number of Statement Extensions 75 | 1 76 | 77 | # Number of original iterators 78 | 1 79 | # List of original iterators 80 | i 81 | # Statement body expression 82 | S[i] = S[i - 2]; 83 | 84 | 85 | # =============================================== Extensions 86 | 87 | b0 i b1 88 | 89 | 90 | 91 | # Number of arrays 92 | 2 93 | # Mapping array-identifiers/array-names 94 | 1 i 95 | 2 S 96 | 97 | 98 | 99 | # File name 100 | unions.c 101 | # Starting line and column 102 | 2 0 103 | # Ending line and column 104 | 10 0 105 | # Indentation 106 | 0 107 | 108 | 109 | 110 | 111 | -------------------------------------------------------------------------------- /examples/visu.c: -------------------------------------------------------------------------------- 1 | #pragma scop 2 | for (int i = 0; i < N; i++) { 3 | for (int j = 0; j < M; j++) { 4 | a[i][j]++; 5 | b[i][j]++; 6 | } 7 | for (int j = 0; j < L; j++) { 8 | c[i][j]++; 9 | } 10 | } 11 | 12 | for (int i = 0; i < A; i++) { 13 | for (int j = 0; j < B; j++) { 14 | for (int k = 0; k < N; k++) { 15 | d[i][j][k]++; 16 | } 17 | } 18 | e[i]++; 19 | } 20 | f++; 21 | #pragma endscop 22 | -------------------------------------------------------------------------------- /macros.h: -------------------------------------------------------------------------------- 1 | #ifndef MACROS_H 2 | #define MACROS_H 3 | 4 | #include 5 | 6 | #define CLINT_WARNING_WARNING 1 7 | #define CLINT_WARNING_INFO 2 8 | #define CLINT_WARNING_DEBUG 3 9 | 10 | #define CLINT_WARNING_LEVEL CLINT_WARNING_DEBUG 11 | 12 | #define CLINT_LEVELED_MESSAGE(condition, text, level) \ 13 | do { \ 14 | if (!(condition)) {_clint_warning_("condition failed" #condition, text, __FILE__, __LINE__, level); } \ 15 | } while (false) \ 16 | 17 | #define CLINT_ASSERT(condition, text) \ 18 | do { \ 19 | if (!(condition)) { _clint_assert_(#condition, text, __FILE__, __LINE__); } \ 20 | } while (false) \ 21 | 22 | #define CLINT_WARNING(condition, text) \ 23 | CLINT_LEVELED_MESSAGE(condition, text, CLINT_WARNING_WARNING) 24 | 25 | #define CLINT_INFO(condition, text) \ 26 | CLINT_LEVELED_MESSAGE(condition, text, CLINT_WARNING_INFO) 27 | 28 | #define CLINT_DEBUG(condition, text) \ 29 | CLINT_LEVELED_MESSAGE(condition, text, CLINT_WARNING_DEBUG) 30 | 31 | #define CLINT_UNREACHABLE \ 32 | _clint_assert_("false", "Unrechable code", __FILE__, __LINE__); 33 | 34 | __attribute__((noreturn)) inline void _clint_assert_(const char *condition, const char *text, const char *filename, unsigned line) { 35 | std::cerr << "ASSERTION FAILED: " << text << " (" << condition << ") at " << filename << ":" << line << std::endl; 36 | #ifndef CLINT_NOFATAL_ASSERTS 37 | std::abort(); 38 | #endif 39 | } 40 | 41 | inline void _clint_fatal_(const char *str) { 42 | std::cerr << "FATAL: " << str << std::endl; 43 | std::abort(); 44 | } 45 | 46 | inline void _clint_warning_(const char *condition, const char *text, const char *filename, unsigned line, int level) { 47 | #ifdef CLINT_WARNING_LEVEL 48 | if (CLINT_WARNING_LEVEL >= level) { 49 | std::cerr << "[Clint] W" << level << ": " << text << " (" << condition << ") at " << filename << ":" << line << std::endl; 50 | } 51 | #endif 52 | } 53 | 54 | #endif // MACROS_H 55 | -------------------------------------------------------------------------------- /main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "clintbeta.h" 5 | #include "clintwindow.h" 6 | 7 | #include "enumerator.h" 8 | #include "oslutils.h" 9 | #include 10 | 11 | namespace { 12 | 13 | void enumerationTest() { 14 | Enumerator *enumerator = new ISLEnumerator; 15 | FILE *file = fopen("enumeration.scop", "r"); 16 | assert(file); 17 | osl_scop_p scop = osl_scop_read(file); 18 | fclose(file); 19 | osl_statement_p statement; 20 | // osl_relation_p fixedParamsContext = oslRelationsFixAllParameters(scop->context, 4); 21 | osl_relation_p fixedParamsContext = osl_relation_clone(scop->context); 22 | LL_FOREACH(statement, scop->statement) { 23 | osl_relation_p relation = oslApplyScattering(statement); 24 | osl_relation_p ready = oslRelationsWithContext(relation, fixedParamsContext); 25 | osl_relation_free(relation); 26 | std::vector dims; 27 | dims.reserve(ready->nb_output_dims); 28 | for (int i = 0; i < ready->nb_output_dims; i++) { 29 | dims.push_back(i); 30 | } 31 | osl_relation_p ready_part; 32 | LL_FOREACH(ready_part, ready) { 33 | osl_relation_p keeper = ready_part->next; 34 | ready_part->next = nullptr; 35 | auto points = enumerator->enumerate(ready_part, dims); 36 | ready_part->next = keeper; 37 | std::for_each(std::begin(points), std::end(points), [](std::vector &p){ 38 | std::copy(std::begin(p), std::end(p), std::ostream_iterator(std::cout, ", ")); 39 | std::cout << std::endl; 40 | }); 41 | } 42 | } 43 | delete enumerator; 44 | } 45 | 46 | } // end anonymous namespace 47 | 48 | int main(int argc, char **argv) { 49 | 50 | qRegisterMetaType(); 51 | 52 | QApplication app(argc, argv); 53 | ClintWindow window; 54 | window.showMaximized(); 55 | 56 | if (app.arguments().contains("--test=enumeration")) { 57 | enumerationTest(); 58 | return 0; 59 | } 60 | 61 | return app.exec(); 62 | } 63 | 64 | -------------------------------------------------------------------------------- /oslutils.h: -------------------------------------------------------------------------------- 1 | #ifndef OSLUTILS_H 2 | #define OSLUTILS_H 3 | 4 | #include 5 | 6 | #include 7 | 8 | #include 9 | 10 | #define CLOOG_INT_GMP 11 | #include 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | /// OpenScop linked-list foreach 19 | #define LL_FOREACH(var, container) \ 20 | for (var = container; var != nullptr; var = var->next) 21 | 22 | template 23 | T *oslListLast(T *container) { 24 | if (container == nullptr) 25 | return nullptr; 26 | while (container->next != nullptr) { 27 | container = container->next; 28 | } 29 | return container; 30 | } 31 | 32 | template 33 | T *oslListTransform(T *container, Func f, Args... args) { 34 | T *result = nullptr, *ptr = nullptr; 35 | if (container == nullptr) { 36 | return nullptr; 37 | } 38 | result = f(container, args...); 39 | ptr = result; 40 | for (T *container_part = container->next; container_part != nullptr; container_part = container_part->next) { 41 | T *result_part = f(container_part, args...); 42 | ptr->next = result_part; 43 | ptr = ptr->next; 44 | } 45 | return result; 46 | } 47 | 48 | /// Call a function on an OSL object as if this object was not part of the list. 49 | /// Function f takes an OSL object of intereset as the first argument, other arguments are optional. 50 | template ::type>::value>::type * = nullptr> 52 | inline auto oslListNoSeqCall(T *ptr, Func f, Args... args) -> decltype(f(ptr, args...)) { 53 | T *keeper = ptr->next; 54 | ptr->next = nullptr; 55 | f(ptr, args...); 56 | ptr->next = keeper; 57 | } 58 | 59 | /// Call a function returning a value for every part of the linked-list OSL object. 60 | /// Function f takes an OSL object of intereset as the first argument, other arguments are optional. 61 | /// If function returns a value, it is ignored. 62 | /// \see oslListTransform to keep the values returned by the function and prevent possible memory leaks. 63 | template ::type>::value>::type * = nullptr> 65 | inline auto oslListNoSeqCall(T *ptr, Func f, Args... args) -> decltype(f(ptr, args...)) { 66 | T *keeper = ptr->next; 67 | ptr->next = nullptr; 68 | auto result = f(ptr, args...); 69 | ptr->next = keeper; 70 | if (std::is_move_assignable::value) { 71 | return std::move(result); 72 | } else { 73 | return result; 74 | } 75 | } 76 | 77 | /// Call a function returning void for every part of the linked-list OSL object. 78 | /// Function f takes an OSL object of intereset as the first argument, other arguments are optional. 79 | /// If function returns a value, it is ignored. 80 | /// \see oslListTransform to keep the values returned by the function and prevent possible memory leaks. 81 | template 82 | inline void oslListForeach(T *container, Func f, Args... args) { 83 | for (T *container_part = container; container_part != nullptr; container_part = container_part->next) { 84 | f(container_part, args...); 85 | } 86 | } 87 | 88 | template 89 | void oslListForeachSingle(T *container, Func f, Args... args) { 90 | auto function = [&](T *ptr, Args... a) { 91 | oslListNoSeqCall(ptr, f, a...); 92 | }; 93 | oslListForeach(container, function, args...); 94 | } 95 | 96 | template 97 | T *oslListPrev(T *var, T *container) { 98 | T *t; 99 | for (t = container; t != nullptr; t = t->next) { 100 | if (t->next == var) { 101 | break; 102 | } 103 | } 104 | return t; 105 | } 106 | 107 | template 108 | std::vector oslListToVector(T *container) { 109 | std::vector vector; 110 | for (T *ptr = container; ptr != nullptr; ptr = ptr->next) { 111 | vector.push_back(ptr); 112 | } 113 | return std::move(vector); 114 | } 115 | 116 | template 117 | T *oslListFromVector(const std::vector &vector) { 118 | if (vector.size() == 0) 119 | return nullptr; 120 | T *head = vector.front(); 121 | T *ptr = head; 122 | for (size_t i = 1; i < vector.size(); i++) { 123 | ptr->next = vector[i]; 124 | ptr = ptr->next; 125 | } 126 | } 127 | 128 | template 129 | int oslListIndexOf(T *container, T *element) { 130 | int index = 0; 131 | bool found = false; 132 | for (T *container_part = container; container_part != nullptr; container_part = container_part->next) { 133 | if (container_part == element) { 134 | found = true; 135 | break; 136 | } 137 | ++index; 138 | } 139 | if (!found) 140 | return -1; 141 | return index; 142 | } 143 | 144 | template 145 | T *oslListAt(T *container, int index) { 146 | int counter = 0; 147 | for (T *container_part = container; container_part != nullptr; container_part = container_part->next) { 148 | if (counter == index) 149 | return container_part; 150 | counter++; 151 | } 152 | return nullptr; 153 | } 154 | 155 | template 156 | int oslListSize(T *container) { 157 | int size = 0; 158 | for (T *container_part = container; container_part != nullptr; container_part = container_part->next) { 159 | size++; 160 | } 161 | return size; 162 | } 163 | 164 | 165 | osl_relation_p oslApplyScattering(osl_statement_p stmt); 166 | osl_relation_p oslApplyScattering(osl_statement_p stmt, const std::vector &beta); 167 | osl_relation_p oslApplyScattering(const std::vector &domains, 168 | const std::vector &scatterings); 169 | 170 | osl_relation_p oslRelationWithContext(osl_relation_p relation, osl_relation_p context); 171 | 172 | osl_relation_p oslRelationFixParameters(osl_relation_p relation, const std::vector> &values); 173 | osl_relation_p oslRelationFixAllParameters(osl_relation_p relation, int value); 174 | 175 | osl_scop_p oslReifyScop(osl_scop_p scop); 176 | 177 | inline osl_relation_p oslRelationsFixParameters(osl_relation_p relation, const std::vector> &values) { 178 | return oslListTransform(relation, &oslRelationFixParameters, values); 179 | } 180 | 181 | inline osl_relation_p oslRelationsFixAllParameters(osl_relation_p relation, int value) { 182 | return oslListTransform(relation, &oslRelationFixAllParameters, value); 183 | } 184 | 185 | inline osl_relation_p oslRelationsWithContext(osl_relation_p relation, osl_relation_p context) { 186 | return oslListTransform(relation, &oslRelationWithContext, context); 187 | } 188 | 189 | int oslRelationDimUpperBound(osl_relation_p relation, int dimension); 190 | int oslRelationDimLowerBound(osl_relation_p relation, int dimension); 191 | 192 | // Vectors are lexicographically-comparable. 193 | typedef std::map, 194 | std::tuple 195 | > BetaMap; 196 | 197 | BetaMap oslBetaMap(osl_scop_p scop); 198 | 199 | // FIXME(osl): we use Clay to access betas; when this functionality is moved to OSL, switch! 200 | std::vector betaFromClay(clay_array_p beta); 201 | clay_array_p clayBetaFromVector(const std::vector &betaVector); 202 | 203 | inline std::vector betaExtract(osl_relation_p relation) { 204 | clay_array_p clay_beta = clay_beta_extract(relation); 205 | std::vector beta = betaFromClay(clay_beta); 206 | clay_array_free(clay_beta); 207 | return std::move(beta); 208 | } 209 | 210 | osl_scop_p oslFromCCode(FILE *file); 211 | osl_scop_p oslFromCCode(char *code); 212 | char *oslToCCode(osl_scop_p scop); 213 | char *fileContents(FILE *file); 214 | 215 | char *escapeHtml(char *); 216 | std::multimap, std::pair> stmtPositionsInCode(osl_scop_p scop); 217 | std::multimap, std::pair> stmtPositionsInHtml(osl_scop_p scop); 218 | 219 | osl_scop_p parseCode(char *code); 220 | int parseClay(osl_scop_p scop, char *script); 221 | 222 | #endif // OSLUTILS_H 223 | -------------------------------------------------------------------------------- /projectionview.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "projectionview.h" 5 | 6 | ProjectionView::ProjectionView(QWidget *parent) : 7 | QGraphicsView(parent) { 8 | } 9 | 10 | ProjectionView::ProjectionView(QGraphicsScene *scene, QWidget *parent) : 11 | QGraphicsView(scene, parent) { 12 | } 13 | 14 | void ProjectionView::mousePressEvent(QMouseEvent *event) { 15 | if (m_active) 16 | QGraphicsView::mousePressEvent(event); 17 | } 18 | 19 | void ProjectionView::mouseReleaseEvent(QMouseEvent *event) { 20 | if (m_active) 21 | QGraphicsView::mouseReleaseEvent(event); 22 | } 23 | 24 | void ProjectionView::mouseMoveEvent(QMouseEvent *event) { 25 | if (m_active) 26 | QGraphicsView::mouseMoveEvent(event); 27 | } 28 | 29 | void ProjectionView::mouseDoubleClickEvent(QMouseEvent *event) { 30 | if (m_active) 31 | QGraphicsView::mouseDoubleClickEvent(event); 32 | emit doubleclicked(); 33 | } 34 | -------------------------------------------------------------------------------- /projectionview.h: -------------------------------------------------------------------------------- 1 | #ifndef PROJECTIONVIEW_H 2 | #define PROJECTIONVIEW_H 3 | 4 | #include 5 | 6 | class ProjectionView : public QGraphicsView { 7 | Q_OBJECT 8 | public: 9 | explicit ProjectionView(QWidget *parent = 0); 10 | explicit ProjectionView(QGraphicsScene *scene, QWidget *parent = 0); 11 | 12 | void setActive(bool active) { 13 | m_active = active; 14 | } 15 | 16 | bool isActive() const { 17 | return m_active; 18 | } 19 | 20 | protected: 21 | void mousePressEvent(QMouseEvent *event); 22 | void mouseReleaseEvent(QMouseEvent *event); 23 | void mouseMoveEvent(QMouseEvent *event); 24 | void mouseDoubleClickEvent(QMouseEvent *event); 25 | 26 | signals: 27 | void doubleclicked(); 28 | 29 | private: 30 | bool m_active = true; 31 | }; 32 | 33 | #endif // PROJECTIONVIEW_H 34 | -------------------------------------------------------------------------------- /propertiesdialog.cpp: -------------------------------------------------------------------------------- 1 | #include "propertiesdialog.h" 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | PropertiesDialog::PropertiesDialog(VizProperties *properties, QWidget *parent) : 8 | QDialog(parent), m_properties(properties) { 9 | 10 | m_pointRadiusEditor = new QLineEdit; 11 | m_pointRadiusEditor->setValidator(new QDoubleValidator(1.0, 42.0, 1, this)); 12 | m_coordinateSystemMarginEditor = new QLineEdit; 13 | m_coordinateSystemMarginEditor->setValidator(new QDoubleValidator(1.0, 42.0, 1, this)); 14 | m_polyhedronOffsetEditor = new QLineEdit; 15 | m_polyhedronOffsetEditor->setValidator(new QDoubleValidator(0.0, 42.0, 1, this)); 16 | m_pointDistanceEditor = new QLineEdit; 17 | m_pointDistanceEditor->setValidator(new QDoubleValidator(1.0, 42.0, 1, this)); 18 | 19 | m_parameterValueEditor = new QLineEdit; 20 | m_parameterValueEditor->setValidator(new QIntValidator(1, 42, this)); 21 | 22 | QFormLayout *layout = new QFormLayout(this); 23 | layout->addRow(new QLabel("Point radius"), m_pointRadiusEditor); 24 | layout->addRow(new QLabel("Point distance"), m_pointDistanceEditor); 25 | layout->addRow(new QLabel("Polyhedron offset"), m_polyhedronOffsetEditor); 26 | layout->addRow(new QLabel("Coordinate system margin"), m_coordinateSystemMarginEditor); 27 | layout->addRow(new QLabel("Parameter value"), m_parameterValueEditor); 28 | 29 | propertyChanged(); 30 | m_parameterValueEditor->setText(QString("6")); 31 | 32 | connect(m_properties, &VizProperties::vizPropertyChanged, this, &PropertiesDialog::propertyChanged); 33 | 34 | connect(m_pointRadiusEditor, &QLineEdit::textChanged, this, &PropertiesDialog::radiusChanged); 35 | connect(m_pointDistanceEditor, &QLineEdit::textChanged, this, &PropertiesDialog::distanceChanged); 36 | connect(m_polyhedronOffsetEditor, &QLineEdit::textChanged, this, &PropertiesDialog::offsetChanged); 37 | connect(m_coordinateSystemMarginEditor, &QLineEdit::textChanged, this, &PropertiesDialog::marginChanged); 38 | 39 | connect(m_parameterValueEditor, &QLineEdit::textChanged, this, &PropertiesDialog::parameterChanged); 40 | } 41 | 42 | PropertiesDialog::~PropertiesDialog() { 43 | disconnect(m_properties, &VizProperties::vizPropertyChanged, this, &PropertiesDialog::propertyChanged); 44 | 45 | disconnect(m_pointRadiusEditor, &QLineEdit::textChanged, this, &PropertiesDialog::radiusChanged); 46 | disconnect(m_pointDistanceEditor, &QLineEdit::textChanged, this, &PropertiesDialog::distanceChanged); 47 | disconnect(m_polyhedronOffsetEditor, &QLineEdit::textChanged, this, &PropertiesDialog::offsetChanged); 48 | disconnect(m_coordinateSystemMarginEditor, &QLineEdit::textChanged, this, &PropertiesDialog::marginChanged); 49 | 50 | disconnect(m_parameterValueEditor, &QLineEdit::textChanged, this, &PropertiesDialog::parameterChanged); 51 | } 52 | 53 | void PropertiesDialog::propertyChanged() { 54 | preventPropagationCycle([this](){ 55 | m_pointDistanceEditor->setText(QString("%1").arg(m_properties->pointDistance())); 56 | m_pointRadiusEditor->setText(QString("%1").arg(m_properties->pointRadius())); 57 | m_polyhedronOffsetEditor->setText(QString("%1").arg(m_properties->polyhedronOffset())); 58 | m_coordinateSystemMarginEditor->setText(QString("%1").arg(m_properties->coordinateSystemMargin())); 59 | }); 60 | } 61 | 62 | void PropertiesDialog::radiusChanged() { 63 | preventPropagationCycle([this](){ 64 | m_properties->setPointRadius(m_pointRadiusEditor->text().toDouble()); 65 | }); 66 | } 67 | 68 | void PropertiesDialog::distanceChanged() { 69 | preventPropagationCycle([this](){ 70 | m_properties->setPointDistance(m_pointDistanceEditor->text().toDouble()); 71 | }); 72 | } 73 | 74 | void PropertiesDialog::offsetChanged() { 75 | preventPropagationCycle([this](){ 76 | m_properties->setPolyhedronOffset(m_polyhedronOffsetEditor->text().toDouble()); 77 | }); 78 | } 79 | 80 | void PropertiesDialog::marginChanged() { 81 | preventPropagationCycle([this](){ 82 | m_properties->setCoordinateSystemMargin(m_coordinateSystemMarginEditor->text().toDouble()); 83 | }); 84 | } 85 | 86 | void PropertiesDialog::parameterChanged() { 87 | int value = m_parameterValueEditor->text().toInt(); 88 | emit parameterChange(value); 89 | } 90 | -------------------------------------------------------------------------------- /propertiesdialog.h: -------------------------------------------------------------------------------- 1 | #ifndef PROPERTIESDIALOG_H 2 | #define PROPERTIESDIALOG_H 3 | 4 | #include "vizproperties.h" 5 | 6 | #include 7 | #include 8 | 9 | class PropertiesDialog : public QDialog { 10 | Q_OBJECT 11 | public: 12 | explicit PropertiesDialog(VizProperties *properties, QWidget *parent = 0); 13 | ~PropertiesDialog(); 14 | 15 | signals: 16 | void parameterChange(int value); 17 | 18 | public slots: 19 | void propertyChanged(); 20 | 21 | void radiusChanged(); 22 | void distanceChanged(); 23 | void offsetChanged(); 24 | void marginChanged(); 25 | 26 | void parameterChanged(); 27 | 28 | private: 29 | VizProperties *m_properties; 30 | 31 | QLineEdit *m_pointDistanceEditor, 32 | *m_pointRadiusEditor, 33 | *m_coordinateSystemMarginEditor, 34 | *m_polyhedronOffsetEditor, 35 | *m_parameterValueEditor; 36 | 37 | bool m_internalChange = false; 38 | template 39 | void preventPropagationCycle(Func f) { 40 | if (m_internalChange) 41 | return; 42 | m_internalChange = true; 43 | f(); 44 | m_internalChange = false; 45 | } 46 | }; 47 | 48 | #endif // PROPERTIESDIALOG_H 49 | -------------------------------------------------------------------------------- /redocmake.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | if [ ! -d build ]; then 4 | mkdir build; 5 | fi 6 | 7 | if [ ! -d release ]; then 8 | mkdir release; 9 | fi 10 | 11 | export CMAKE_PREFIX_PATH=$HOME/usr:$CMAKE_PREFIX_PATH 12 | cd build 13 | cmake .. -DCMAKE_BUILD_TYPE=Debug 14 | make 15 | cd - 16 | 17 | cd release 18 | cmake .. -DCMAKE_BUILD_TYPE=Release 19 | make 20 | cd - 21 | -------------------------------------------------------------------------------- /transformation.cpp: -------------------------------------------------------------------------------- 1 | #include "transformation.h" 2 | -------------------------------------------------------------------------------- /transformation.h: -------------------------------------------------------------------------------- 1 | #ifndef TRANSFORMATION_H 2 | #define TRANSFORMATION_H 3 | 4 | #include 5 | #include 6 | 7 | #include "macros.h" 8 | 9 | class Transformation { 10 | public: 11 | enum class Kind { 12 | Shift, 13 | Skew, 14 | Fuse, 15 | Split, 16 | Reorder, 17 | IndexSetSplitting, 18 | Grain, 19 | Reverse, 20 | Interchange, 21 | Tile, 22 | Linearize, 23 | Reshape, 24 | Densify, 25 | Collapse, 26 | Embed, 27 | Unembed 28 | }; 29 | 30 | Kind kind() const { 31 | return m_kind; 32 | } 33 | 34 | const std::vector &target() const { 35 | return m_targetBeta; 36 | } 37 | 38 | int depth() const { 39 | return m_depthOuter; 40 | } 41 | 42 | int secondDepth() const { 43 | return m_depthInner; 44 | } 45 | 46 | int constantAmount() const { 47 | return m_constantAmount; 48 | } 49 | 50 | const std::vector &order() const { 51 | return m_order; 52 | } 53 | 54 | const std::vector ¶meters() const { 55 | return m_parameters; 56 | } 57 | 58 | const std::vector &iterators() const { 59 | return m_iterators; 60 | } 61 | 62 | static Transformation constantShift(const std::vector &beta, int dimension, int amount) { 63 | CLINT_ASSERT(dimension <= beta.size(), "Dimension overflow"); 64 | Transformation t; 65 | t.m_kind = Kind::Shift; 66 | t.m_targetBeta = beta; 67 | t.m_depthOuter = dimension; 68 | t.m_constantAmount = amount; 69 | return t; 70 | } 71 | 72 | static Transformation skew(const std::vector &beta, int targetDimension, int sourceDimension, int factor) { 73 | CLINT_ASSERT(sourceDimension <= beta.size(), "Dimension overflow"); 74 | CLINT_ASSERT(targetDimension <= beta.size(), "Dimension overflow"); 75 | Transformation t; 76 | t.m_kind = Kind::Skew; 77 | t.m_targetBeta = beta; 78 | t.m_depthInner = sourceDimension; 79 | t.m_depthOuter = targetDimension; 80 | t.m_constantAmount = factor; 81 | return t; 82 | } 83 | 84 | static Transformation reshape(const std::vector &beta, int outputDimension, int inputDimension, int factor) { 85 | CLINT_ASSERT(outputDimension <= beta.size(), "Dimension overflow"); 86 | CLINT_ASSERT(inputDimension <= beta.size(), "Dimension overflow"); 87 | CLINT_ASSERT(outputDimension >= 0, "Dimension underflow"); 88 | CLINT_ASSERT(inputDimension >= 0, "Dimension underflow"); 89 | Transformation t; 90 | t.m_kind = Kind::Reshape; 91 | t.m_targetBeta = beta; 92 | t.m_depthInner = inputDimension; 93 | t.m_depthOuter = outputDimension; 94 | t.m_constantAmount = factor; 95 | return t; 96 | } 97 | 98 | static Transformation issFromConstraint(const std::vector &beta, 99 | const std::vector &issConstraint, 100 | size_t nbInputDims) { 101 | CLINT_ASSERT(beta.size() >= 1, "Beta too short"); 102 | CLINT_ASSERT(issConstraint.size() - 1 - nbInputDims > 0, 103 | "Input dimension number is wrong"); 104 | Transformation t; 105 | t.m_kind = Kind::IndexSetSplitting; 106 | t.m_targetBeta = beta; 107 | t.m_constantAmount = issConstraint.back(); 108 | t.m_iterators = std::vector(std::begin(issConstraint) + 1, 109 | std::begin(issConstraint) + 1 + nbInputDims); 110 | t.m_parameters = std::vector(std::begin(issConstraint) + 1 + nbInputDims, 111 | std::end(issConstraint) - 1); 112 | return t; 113 | 114 | } 115 | 116 | static Transformation grain(const std::vector &beta, int depth, int value) { 117 | CLINT_ASSERT(beta.size() >= 1, "Beta too short"); 118 | Transformation t; 119 | t.m_kind = Kind::Grain; 120 | t.m_targetBeta = beta; 121 | t.m_constantAmount = value; 122 | t.m_depthOuter = depth; 123 | return t; 124 | } 125 | 126 | static Transformation putAfterLast(const std::vector &beta, int size) { 127 | CLINT_ASSERT(beta.size() >= 1, "Cannot operate on the whole program"); 128 | return putAfter(beta, size - 1, size); 129 | // Transformation t; 130 | // t.m_kind = Kind::Reorder; 131 | // t.m_targetBeta = std::vector(std::begin(beta), std::end(beta) - 1); 132 | // t.m_order.resize(size); 133 | // for (int i = 0; i < size; i++) { 134 | // if (i < beta.back()) 135 | // t.m_order[i] = i; 136 | // else if (i == beta.back()) 137 | // t.m_order[i] = size - 1; 138 | // else 139 | // t.m_order[i] = i - 1; 140 | // } 141 | // return t; 142 | } 143 | 144 | static Transformation putAfter(const std::vector &beta, int position, int size) { 145 | CLINT_ASSERT(beta.size() >= 1, "Cannot operate on the whole program"); 146 | CLINT_ASSERT(size > position, "Position of the element to put after overflow"); 147 | if (beta.back() > position) { 148 | std::vector b(beta); 149 | int tmp = position; 150 | position = b.back(); 151 | b.back() = tmp; 152 | return putAfter(b, position, size); 153 | } 154 | // if (beta.back() > position) { 155 | // return putBefore(beta, position + 1, size); 156 | // } 157 | 158 | Transformation t; 159 | t.m_kind = Kind::Reorder; 160 | t.m_targetBeta = std::vector(std::begin(beta), std::end(beta) - 1); 161 | t.m_order.resize(size); 162 | for (int i = 0; i < size; i++) { 163 | if (i > beta.back() && i <= position) 164 | t.m_order[i] = i - 1; 165 | else if (i == beta.back()) 166 | t.m_order[i] = position; 167 | else 168 | t.m_order[i] = i; 169 | } 170 | return t; 171 | } 172 | 173 | static Transformation putBefore(const std::vector &beta, int position, int size) { 174 | CLINT_ASSERT(beta.size() >= 1, "Cannot operate on the whole program"); 175 | CLINT_ASSERT(size >= position, "Position of the element to put after overflow"); 176 | if (position > beta.back()) { 177 | return putAfter(beta, position - 1, size); 178 | } 179 | 180 | Transformation t; 181 | t.m_kind = Kind::Reorder; 182 | t.m_targetBeta = std::vector(std::begin(beta), std::end(beta) - 1); 183 | t.m_order.resize(size); 184 | for (int i = 0; i < size; i++) { 185 | if (i >= position && i < beta.back()) { 186 | t.m_order[i] = i + 1; 187 | } else if (i == beta.back()) { 188 | t.m_order[i] = position; 189 | } else { 190 | t.m_order[i] = i; 191 | } 192 | } 193 | return t; 194 | } 195 | 196 | static Transformation splitAfter(const std::vector &beta) { 197 | CLINT_ASSERT(beta.size() >= 1, "Cannot operate on the whole program"); 198 | Transformation t; 199 | t.m_kind = Kind::Split; 200 | t.m_targetBeta = beta; 201 | t.m_depthOuter = beta.size() - 1; 202 | return t; 203 | } 204 | 205 | static Transformation fuseNext(const std::vector &beta) { 206 | CLINT_ASSERT(beta.size() >= 1, "Cannot operate on the whole program"); 207 | Transformation t; 208 | t.m_kind = Kind::Fuse; 209 | t.m_targetBeta = beta; 210 | t.m_depthOuter = beta.size(); 211 | return t; 212 | } 213 | 214 | static Transformation reverse(const std::vector &beta, int dimension) { 215 | CLINT_ASSERT(beta.size() >= 1, "Cannot operate on the whole program"); 216 | Transformation t; 217 | t.m_kind = Kind::Reverse; 218 | t.m_targetBeta = beta; 219 | t.m_depthOuter = dimension; 220 | return t; 221 | } 222 | 223 | static Transformation interchange(const std::vector &beta, int dimension1, int dimension2) { 224 | CLINT_ASSERT(beta.size() >= std::max(dimension1, dimension2), 225 | "Beta too short"); 226 | Transformation t; 227 | t.m_kind = Kind::Interchange; 228 | t.m_targetBeta = beta; 229 | t.m_depthInner = dimension1; 230 | t.m_depthOuter = dimension2; 231 | return t; 232 | } 233 | 234 | static Transformation tile(const std::vector &beta, int dimension, int size) { 235 | CLINT_ASSERT(beta.size() >= dimension, 236 | "Beta too short"); 237 | Transformation t; 238 | t.m_kind = Kind::Tile; 239 | t.m_targetBeta = beta; 240 | t.m_depthOuter = dimension; 241 | t.m_constantAmount = size; 242 | return t; 243 | } 244 | 245 | static Transformation linearize(const std::vector &beta, int dimension) { 246 | CLINT_ASSERT(beta.size() >= dimension, 247 | "Beta too short"); 248 | Transformation t; 249 | t.m_kind = Kind::Linearize; 250 | t.m_targetBeta = beta; 251 | t.m_depthOuter = dimension; 252 | return t; 253 | } 254 | 255 | static Transformation densify(const std::vector &beta, int dimension) { 256 | CLINT_ASSERT(beta.size() >= dimension, "Beta too short"); 257 | Transformation t; 258 | t.m_kind = Kind::Densify; 259 | t.m_targetBeta = beta; 260 | t.m_depthOuter = dimension; 261 | return t; 262 | } 263 | 264 | static Transformation embed(const std::vector &beta) { 265 | Transformation t; 266 | t.m_kind = Kind::Embed; 267 | t.m_targetBeta = beta; 268 | return t; 269 | } 270 | 271 | static Transformation unembed(const std::vector &beta) { 272 | Transformation t; 273 | t.m_kind = Kind::Unembed; 274 | t.m_targetBeta = beta; 275 | return t; 276 | } 277 | 278 | static Transformation collapse(const std::vector &beta) { 279 | Transformation t; 280 | t.m_kind = Kind::Collapse; 281 | t.m_targetBeta = beta; 282 | return t; 283 | } 284 | 285 | /*+*********** raw transformations from parser *************/ 286 | static Transformation rawSplit(const std::vector &beta, int dimension) { 287 | CLINT_ASSERT(beta.size() > 0, "Split transformation beta too short"); 288 | CLINT_ASSERT(dimension <= beta.size(), "Split transformation dimension overflow"); 289 | CLINT_ASSERT(dimension > 0, "Split transformation dimension underflow"); 290 | Transformation t; 291 | t.m_kind = Kind::Split; 292 | t.m_targetBeta = beta; 293 | t.m_depthOuter = dimension; 294 | return t; 295 | } 296 | 297 | static Transformation rawReorder(const std::vector &beta, const std::vector &order) { 298 | Transformation t; 299 | t.m_kind = Kind::Reorder; 300 | t.m_targetBeta = beta; 301 | t.m_order = order; 302 | return t; 303 | } 304 | 305 | static Transformation rawShift(const std::vector &beta, int depth, const std::vector ¶meters, int constant) { 306 | CLINT_ASSERT(beta.size() > 0, "Shift transformation beta too short"); 307 | CLINT_ASSERT(depth <= beta.size(), "Shift transformation depth overflow"); 308 | CLINT_ASSERT(depth > 0, "Shift transformation depth underflow"); 309 | Transformation t; 310 | t.m_kind = Kind::Shift; 311 | t.m_targetBeta = beta; 312 | t.m_depthOuter = depth; 313 | t.m_parameters = parameters; 314 | t.m_constantAmount = constant; 315 | return t; 316 | } 317 | 318 | static Transformation rawTile(const std::vector &beta, int innerDepth, int outerDepth, int size, int pretty) { 319 | CLINT_ASSERT(beta.size() > 0, "Tile transformation beta too short"); 320 | (void) pretty; 321 | (void) outerDepth; 322 | return Transformation::tile(beta, innerDepth, size); 323 | } 324 | 325 | static Transformation rawIss(const std::vector &beta, const std::vector> &list) { 326 | CLINT_ASSERT(beta.size() > 0, "Iss transformation beta too short"); 327 | Transformation t; 328 | t.m_kind = Kind::IndexSetSplitting; 329 | t.m_targetBeta = beta; 330 | unwrapClayList(list, t); 331 | return t; 332 | } 333 | 334 | private: 335 | std::vector m_targetBeta; 336 | int m_depthInner, m_depthOuter; 337 | int m_constantAmount; 338 | std::vector m_order; 339 | 340 | std::vector m_parameters; 341 | std::vector m_iterators; 342 | 343 | Kind m_kind; 344 | 345 | static void unwrapClayList(const std::vector> &list, Transformation &t) { 346 | CLINT_ASSERT(list.size() == 4, "List malformed"); 347 | CLINT_ASSERT(list[3].size() <= 1, "More than one value for constant part of the list"); 348 | CLINT_ASSERT(list[0].size() != 0 || list[1].size() != 0 || list[2].size() != 0, 349 | "Empty list in transformation"); 350 | t.m_iterators = list[0]; 351 | t.m_parameters = list[2]; 352 | t.m_constantAmount = list[3].size() == 1 ? list[3][0] : 0; 353 | } 354 | }; 355 | 356 | struct TransformationGroup { 357 | std::vector transformations; 358 | }; 359 | 360 | struct TransformationSequence { 361 | std::vector groups; 362 | }; 363 | 364 | #endif // TRANSFORMATION_H 365 | -------------------------------------------------------------------------------- /uninstall.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -x 3 | set -e 4 | 5 | if [ -z ${PREFIX+x} ]; then 6 | PREFIX=$HOME/usr 7 | fi; 8 | 9 | for i in isl openscop cloog clan candl clay; do 10 | cd $i; 11 | make uninstall; 12 | cd -; 13 | done 14 | 15 | cd chlore/build 16 | make uninstall 17 | cd - 18 | 19 | cd build 20 | make uninstall 21 | cd - 22 | -------------------------------------------------------------------------------- /vizcoordinatesystem.h: -------------------------------------------------------------------------------- 1 | #ifndef VIZCOORDINATESYSTEM_H 2 | #define VIZCOORDINATESYSTEM_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include "clintprogram.h" 10 | #include "clintscop.h" 11 | #include "clintstmt.h" 12 | #include "vizproperties.h" 13 | 14 | class VizPolyhedron; 15 | class VizProjection; 16 | class VizDepArrow; 17 | 18 | class VizCoordinateSystem : public QGraphicsObject { 19 | Q_OBJECT 20 | public: 21 | enum class AxisState { 22 | Invisible, 23 | Visible, 24 | WillAppear, 25 | WillDisappear 26 | }; 27 | 28 | explicit VizCoordinateSystem(VizProjection *projection, 29 | size_t horizontalDimensionIdx = VizProperties::NO_DIMENSION, 30 | size_t verticalDimensionIdx = VizProperties::NO_DIMENSION, 31 | QGraphicsItem *parent = nullptr); 32 | 33 | QSet visibleScops() { 34 | QSet stmts = m_program->statementsInCoordinateSystem(this); 35 | QSet scops; 36 | for (ClintStmt *stmt : stmts) { 37 | scops.insert(stmt->scop()); 38 | } 39 | return scops; 40 | } 41 | 42 | const ClintProgram *program() const { 43 | return m_program; 44 | } 45 | 46 | VizProjection *projection() const { 47 | return m_projection; 48 | } 49 | 50 | void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); 51 | QRectF boundingRect() const; 52 | 53 | bool isHorizontalAxisVisible() const { 54 | return m_horizontalAxisState == AxisState::Visible; 55 | } 56 | 57 | bool isVerticalAxisVisible() const { 58 | return m_verticalAxisState == AxisState::Visible; 59 | } 60 | 61 | void setHorizontalAxisState(VizCoordinateSystem::AxisState state) { 62 | bool scheduleRepaint = (state != m_horizontalAxisState); 63 | m_horizontalAxisState = state; 64 | if (scheduleRepaint) { 65 | update(); 66 | } 67 | } 68 | 69 | void setVerticalAxisState(VizCoordinateSystem::AxisState state) { 70 | bool scheduleRepaint = (state != m_verticalAxisState); 71 | m_verticalAxisState = state; 72 | if (scheduleRepaint) { 73 | update(); 74 | } 75 | } 76 | 77 | size_t horizontalDimensionIdx() const { 78 | return m_horizontalDimensionIdx; 79 | } 80 | 81 | size_t verticalDimensionIdx() const { 82 | return m_verticalDimensionIdx; 83 | } 84 | 85 | void setHorizontalDimensionIdx(size_t dimIdx); 86 | void setVerticalDimensionIdx(size_t dimIdx); 87 | 88 | QRectF coordinateSystemRect() const; 89 | 90 | bool projectStatementOccurrence(ClintStmtOccurrence *occurrence); 91 | void updateInnerDependences(); 92 | void updateInternalDependences(); 93 | void setInnerDependencesBetween(VizPolyhedron *vp1, VizPolyhedron *vp2, std::vector> &&lines, bool violated); 94 | 95 | void extendHorizontally(int minimum, int maximum) { 96 | m_horizontalMin = std::min(m_horizontalMin, minimum); 97 | m_horizontalMax = std::max(m_horizontalMax, maximum); 98 | } 99 | 100 | void extendVertically(int minimum, int maximum) { 101 | m_verticalMin = std::min(m_verticalMin, minimum); 102 | m_verticalMax = std::max(m_verticalMax, maximum); 103 | } 104 | 105 | void setMinMax(int horizontalMinimum, int horizontalMaximum, 106 | int verticalMinimum, int verticalMaximum); 107 | void setHorizontalMinMax(int horizontalMinimum, int horizontalMaximum); 108 | void setVerticalMinMax(int verticalMinimum, int verticalMaximum); 109 | 110 | void setMinMax(const std::pair &horizontal, 111 | const std::pair &vertical) { 112 | setMinMax(horizontal.first, horizontal.second, 113 | vertical.first, vertical.second); 114 | } 115 | void setHorizontalMinMax(const std::pair &horizontal) { 116 | setHorizontalMinMax(horizontal.first, horizontal.second); 117 | } 118 | void setVerticalMinMax(const std::pair &vertical) { 119 | setVerticalMinMax(vertical.first, vertical.second); 120 | } 121 | 122 | void minMax(int &horizontalMinimum, int &horizontalMaximum, 123 | int &verticalMinimum, int &verticalMaximum) { 124 | horizontalMinimum = m_horizontalMin; 125 | horizontalMaximum = m_horizontalMax; 126 | verticalMinimum = m_verticalMin; 127 | verticalMaximum = m_verticalMax; 128 | } 129 | 130 | bool isEmpty() const { 131 | return m_polyhedra.empty(); 132 | } 133 | 134 | int countPolyhedra() const { 135 | return m_polyhedra.size(); 136 | } 137 | 138 | VizPolyhedron *polyhedron(const std::vector &beta) const; 139 | 140 | std::vector betaPrefix() const; 141 | 142 | int dependentWith(VizCoordinateSystem *vcs); 143 | bool nextCsIsDependent = false; 144 | bool nextPileIsDependent = false; 145 | bool nextCsIsViolated = false; 146 | bool nextPileIsViolated = false; 147 | 148 | int horizontalAxisLength() const; 149 | int verticalAxisLength() const; 150 | int ticMargin() const; 151 | 152 | void polyhedronUpdated(VizPolyhedron *polyhedron); 153 | void setPolyhedronCoordinates(VizPolyhedron *polyhedron, int horizontal, int vertical, 154 | bool ignoreHorizontal = false, bool ignoreVertical = false); 155 | void reparentPolyhedron(VizPolyhedron *polyhedron); 156 | void resetPolyhedronPos(VizPolyhedron *polyhedron); 157 | 158 | void insertPolyhedronAfter(VizPolyhedron *inserted, VizPolyhedron *after); 159 | void removePolyhedron(VizPolyhedron *polyhedron); 160 | void updateAllPositions(); 161 | void deleteInnerDependences(); 162 | 163 | signals: 164 | 165 | public slots: 166 | 167 | private: 168 | std::vector m_polyhedra; 169 | ClintProgram *m_program; 170 | VizProjection *m_projection; 171 | std::unordered_set m_depArrows; 172 | 173 | size_t m_horizontalDimensionIdx = VizProperties::UNDEFINED_DIMENSION; 174 | size_t m_verticalDimensionIdx = VizProperties::UNDEFINED_DIMENSION; 175 | 176 | AxisState m_horizontalAxisState = AxisState::Visible; 177 | AxisState m_verticalAxisState = AxisState::Visible; 178 | 179 | /// @variable m_horizontalMin 180 | /// @variable m_horizontalMax 181 | /// @variable m_verticalMin 182 | /// @variable m_verticalMax 183 | /// @brief Minimum and maximum values (inclusive) for the coordinate system. 184 | /// By deafult, center coordinate system at (0, 0) with 1x1 span. 185 | /// Call setMinMax(int, int, int, int) to change the coordinate system span. 186 | /// When projectStatementOccurrence(ClintStmtOccurrence *) is called, 187 | /// the coordinate system is extended so that it accommodates both the origin 188 | /// point (0, 0) and the projection of statement occurrence. 189 | int m_horizontalMin = 0; 190 | int m_horizontalMax = 0; 191 | int m_verticalMin = 0; 192 | int m_verticalMax = 0; 193 | 194 | QFont m_font; 195 | QString m_horizontalName; 196 | QString m_verticalName; 197 | 198 | void addAxisLabels(ClintStmtOccurrence *occurrence); 199 | void regenerateAxisLabels(); 200 | void updatePolyhedraPositions(); 201 | QPolygonF leftArrow(int length, const double pointRadius); 202 | QPolygonF topArrow(int length, const double pointRadius); 203 | 204 | }; 205 | 206 | #endif // VIZCOORDINATESYSTEM_H 207 | -------------------------------------------------------------------------------- /vizdeparrow.cpp: -------------------------------------------------------------------------------- 1 | #include "vizdeparrow.h" 2 | #include "vizpolyhedron.h" 3 | #include "vizprojection.h" 4 | #include "vizpoint.h" 5 | 6 | #include 7 | #include 8 | 9 | VizDepArrow::VizDepArrow(QPointF source, QPointF target, VizPolyhedron *parent, bool violated) : 10 | QGraphicsObject(parent), m_coordinateSystemParent(nullptr), m_violated(violated) { 11 | 12 | m_vizProperties = parent->coordinateSystem()->projection()->vizProperties(); 13 | pointLink(source, target); 14 | } 15 | 16 | VizDepArrow::VizDepArrow(QPointF source, QPointF target, VizCoordinateSystem *parent, bool violated) : 17 | QGraphicsObject(parent), m_coordinateSystemParent(parent), m_violated(violated) { 18 | 19 | m_vizProperties = parent->projection()->vizProperties(); 20 | pointLink(source, target); 21 | } 22 | 23 | VizDepArrow::VizDepArrow(VizPoint *source, VizPoint *target, VizPolyhedron *parent, bool violated) : 24 | VizDepArrow(source->pos(), target->pos(), parent, violated) { 25 | m_vizProperties = parent->coordinateSystem()->projection()->vizProperties(); 26 | m_sourcePoint = source; 27 | m_targetPoint = target; 28 | 29 | connect(source, &VizPoint::positionChanged, this, &VizDepArrow::repoint); 30 | connect(target, &VizPoint::positionChanged, this, &VizDepArrow::repoint); 31 | } 32 | 33 | void VizDepArrow::pointLinkCS(VizPoint *source, VizPoint *target) { 34 | QPointF sourcePoint = source->parentItem()->mapToItem(m_coordinateSystemParent, source->pos()); 35 | QPointF targetPoint = target->parentItem()->mapToItem(m_coordinateSystemParent, target->pos()); 36 | pointLink(sourcePoint, targetPoint); 37 | } 38 | 39 | VizDepArrow::VizDepArrow(VizPoint *source, VizPoint *target, VizCoordinateSystem *parent, bool violated) : 40 | QGraphicsObject(parent), m_sourcePoint(source), m_targetPoint(target), m_coordinateSystemParent(parent), m_violated(violated) { 41 | 42 | m_vizProperties = parent->projection()->vizProperties(); 43 | pointLinkCS(source, target); 44 | 45 | connect(source, &VizPoint::positionChanged, this, &VizDepArrow::repoint); 46 | connect(target, &VizPoint::positionChanged, this, &VizDepArrow::repoint); 47 | connect(source->polyhedron(), &VizPolyhedron::positionChanged, this, &VizDepArrow::repoint); 48 | connect(target->polyhedron(), &VizPolyhedron::positionChanged, this, &VizDepArrow::repoint); 49 | } 50 | 51 | void VizDepArrow::repoint() { 52 | if (!m_sourcePoint || !m_targetPoint) 53 | return; 54 | 55 | if (m_coordinateSystemParent) { 56 | pointLinkCS(m_sourcePoint, m_targetPoint); 57 | } else { 58 | pointLink(m_sourcePoint->pos(), m_targetPoint->pos()); 59 | } 60 | } 61 | 62 | void VizDepArrow::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) { 63 | Q_UNUSED(option); 64 | Q_UNUSED(widget); 65 | 66 | painter->setRenderHint(QPainter::Antialiasing); 67 | if (m_violated) { 68 | painter->setPen(Qt::red); 69 | painter->setBrush(Qt::red); 70 | } 71 | painter->drawLine(m_arrowLine); 72 | painter->fillPath(m_arrowHead, QBrush(Qt::black)); 73 | } 74 | 75 | QRectF VizDepArrow::boundingRect() const { 76 | // Since arrow head has a 60-degree angle, it will be covered by a rectangle 77 | // (with a 90-degree angle, obviously) ending at the head's sharp end. This sharp end 78 | // lies on the arrow line, pointRadius pixels after the arrow line ends. 79 | const double pointRadius = m_vizProperties->pointRadius(); 80 | QLineF diagonal(m_arrowLine); 81 | diagonal.setLength(diagonal.length() + pointRadius); 82 | return QRectF(m_arrowLine.p1(), m_arrowLine.p2()); 83 | } 84 | 85 | void VizDepArrow::pointLink(QPointF source, QPointF target) { 86 | // Set the line so that it starts on the border of the first point's circle, and ends pointRadius 87 | // pixels before the second point's circle in order to put the arrow head there. 88 | const double pointRadius = m_vizProperties->pointRadius(); 89 | m_arrowLine = QLineF(source, target); 90 | qreal length = m_arrowLine.length(); 91 | QLineF displacementLine = QLineF(m_arrowLine); 92 | displacementLine.setLength(pointRadius); 93 | // Now p2 of displacement line has the coordinates p1 of the shorter line should have. 94 | m_arrowLine.setLength(length - 2. * pointRadius); 95 | m_arrowLine.setP1(displacementLine.p2()); 96 | 97 | // Compute an arrow path of the style )>. 98 | // Head is based on the triangle with equal sides and an arc. 99 | // Center of the arc touches the arrow line, side angles are 1/4 R back along this line. 100 | // Hence triangle height is H = R + 1/4 R. 101 | // Thus length of the triangle side is, L = 5 / 2 / sqrt(3) R, 102 | // where R is point readius. 103 | const double halfside = 5.0 * pointRadius / 4.0 / sqrt(3.0); 104 | QPainterPath headPath; 105 | headPath.moveTo(-halfside, pointRadius / 4.0); 106 | headPath.lineTo(0, -pointRadius); 107 | headPath.lineTo(halfside, pointRadius / 4.0); 108 | const double angle = acos(halfside / pointRadius); 109 | headPath.arcTo(-pointRadius, 0, 2.0 * pointRadius, 2.0 * pointRadius, 110 | 90 - (angle * 180) / M_PI, 111 | 2 * (angle * 180) / M_PI); 112 | QTransform transform; 113 | transform.rotate(90 - m_arrowLine.angle()); 114 | headPath = transform.map(headPath); 115 | transform.reset(); 116 | transform.translate(m_arrowLine.p2().x(), m_arrowLine.p2().y()); 117 | m_arrowHead = transform.map(headPath); 118 | } 119 | -------------------------------------------------------------------------------- /vizdeparrow.h: -------------------------------------------------------------------------------- 1 | #ifndef VIZDEPARROW_H 2 | #define VIZDEPARROW_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #include "vizproperties.h" 9 | #include "vizpoint.h" 10 | #include "vizpolyhedron.h" 11 | 12 | #include 13 | 14 | class VizDepArrow : public QGraphicsObject { 15 | public: 16 | VizDepArrow(QPointF source, QPointF target, VizPolyhedron *parent, bool violated); 17 | VizDepArrow(QPointF source, QPointF target, VizCoordinateSystem *parent, bool violated); 18 | 19 | VizDepArrow(VizPoint *source, VizPoint *target, VizPolyhedron *parent, bool violated); 20 | VizDepArrow(VizPoint *source, VizPoint *target, VizCoordinateSystem *parent, bool violated); 21 | 22 | void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); 23 | QRectF boundingRect() const; 24 | 25 | private slots: 26 | void repoint(); 27 | 28 | private: 29 | void pointLink(QPointF source, QPointF target); 30 | void pointLinkCS(VizPoint *source, VizPoint *target); 31 | 32 | VizPoint *m_sourcePoint = nullptr, 33 | *m_targetPoint = nullptr; 34 | VizCoordinateSystem *m_coordinateSystemParent = nullptr; 35 | 36 | bool m_violated; 37 | QLineF m_arrowLine; 38 | QPainterPath m_arrowHead; 39 | const VizProperties *m_vizProperties; 40 | }; 41 | 42 | template 43 | void vizDependenceArrowsCreate(VizPolyhedron *sourcePolyhedron, 44 | VizPolyhedron *targetPolyhedron, 45 | std::vector > &&dependences, 46 | bool violated, 47 | ParentType *parentObject, 48 | std::unordered_set &set) { 49 | int sourceInputDimensionality = sourcePolyhedron->occurrence()->inputDimensionality(); 50 | int targetInputDimensionality = targetPolyhedron->occurrence()->inputDimensionality(); 51 | 52 | typedef std::pair, std::pair> DepCoordinates; 53 | std::unordered_set> existingDependences; 54 | 55 | for (const std::vector &dep : dependences) { 56 | CLINT_ASSERT(sourceInputDimensionality + targetInputDimensionality <= dep.size(), 57 | "Not enough dimensions in a dependence projection"); 58 | std::vector sourceCoordinates(std::begin(dep), 59 | std::begin(dep) + sourceInputDimensionality); 60 | std::vector targetCoordinates(std::begin(dep) + sourceInputDimensionality, 61 | std::begin(dep) + sourceInputDimensionality + targetInputDimensionality); 62 | 63 | VizPoint *sourcePoint = sourcePolyhedron->point(sourceCoordinates), 64 | *targetPoint = targetPolyhedron->point(targetCoordinates); 65 | 66 | if (!sourcePoint || !targetPoint) 67 | continue; 68 | 69 | DepCoordinates depCoordinates = std::make_pair(sourcePoint->scatteredCoordinates(), 70 | targetPoint->scatteredCoordinates()); 71 | 72 | // Omit self-dependences. 73 | if (depCoordinates.first == depCoordinates.second) 74 | continue; 75 | 76 | if (existingDependences.count(depCoordinates) == 0) { 77 | VizDepArrow *depArrow = new VizDepArrow(sourcePoint, targetPoint, 78 | parentObject, violated); 79 | if (violated) { 80 | depArrow->setZValue(100); 81 | } else { 82 | depArrow->setZValue(42); 83 | } 84 | set.insert(depArrow); 85 | existingDependences.emplace(depCoordinates); 86 | } 87 | } 88 | } 89 | #endif // VIZDEPARROW_H 90 | -------------------------------------------------------------------------------- /vizhandle.cpp: -------------------------------------------------------------------------------- 1 | #include "vizhandle.h" 2 | #include "macros.h" 3 | #include 4 | #include 5 | #include 6 | 7 | #include 8 | 9 | constexpr int VizHandle::updates[VizHandle::NB_KINDS][VizHandle::NB_KINDS]; 10 | 11 | VizHandle::VizHandle(QGraphicsItem *item, Kind kind) : 12 | QGraphicsRectItem(item), m_kind(kind) { 13 | 14 | setFlag(QGraphicsItem::ItemSendsGeometryChanges); 15 | setFlag(QGraphicsItem::ItemIsMovable); 16 | setAcceptHoverEvents(true); 17 | 18 | recomputePos(); 19 | setZValue(1000); 20 | 21 | setBrush(QBrush(Qt::black)); 22 | } 23 | 24 | void VizHandle::recomputePos() { 25 | double x,y; 26 | if (!parentItem()) 27 | return; 28 | 29 | setPos(0, 0); 30 | 31 | QRectF parentBoundingRect = parentItem()->boundingRect(); 32 | 33 | switch (m_kind) { 34 | case Kind::LEFT: 35 | x = parentBoundingRect.left(); 36 | y = parentBoundingRect.center().y(); 37 | break; 38 | case Kind::RIGHT: 39 | x = parentBoundingRect.right(); 40 | y = parentBoundingRect.center().y(); 41 | break; 42 | case Kind::TOP: 43 | x = parentBoundingRect.center().x(); 44 | y = parentBoundingRect.top(); 45 | break; 46 | case Kind::BOTTOM: 47 | x = parentBoundingRect.center().x(); 48 | y = parentBoundingRect.bottom(); 49 | break; 50 | case Kind::TOPLEFT: 51 | x = parentBoundingRect.left(); 52 | y = parentBoundingRect.top(); 53 | break; 54 | case Kind::TOPRIGHT: 55 | x = parentBoundingRect.right(); 56 | y = parentBoundingRect.top(); 57 | break; 58 | case Kind::BOTTOMLEFT: 59 | x = parentBoundingRect.left(); 60 | y = parentBoundingRect.bottom(); 61 | break; 62 | case Kind::BOTTOMRIGHT: 63 | x = parentBoundingRect.right(); 64 | y = parentBoundingRect.bottom(); 65 | break; 66 | default: 67 | CLINT_UNREACHABLE; 68 | } 69 | 70 | setRect(x - m_size / 2, y - m_size / 2, m_size, m_size); 71 | } 72 | 73 | QVariant VizHandle::itemChange(GraphicsItemChange change, const QVariant &value) { 74 | if (change == QGraphicsItem::ItemPositionChange && m_pressed) { 75 | QPointF oldPos = pos(); 76 | QPointF newPos = value.toPointF(); 77 | switch (m_kind) { 78 | case Kind::LEFT: 79 | case Kind::RIGHT: 80 | newPos.ry() = oldPos.y(); 81 | break; 82 | 83 | case Kind::TOP: 84 | case Kind::BOTTOM: 85 | newPos.rx() = oldPos.x(); 86 | break; 87 | default: 88 | break; 89 | } 90 | return QVariant::fromValue(newPos); 91 | } 92 | return QGraphicsRectItem::itemChange(change, value); 93 | } 94 | 95 | void VizHandle::mousePressEvent(QGraphicsSceneMouseEvent *event) { 96 | QGraphicsRectItem::mousePressEvent(event); 97 | 98 | m_modifier = event->modifiers() & Qt::ShiftModifier; 99 | emit aboutToMove(this); 100 | 101 | m_pressPos = pos(); 102 | m_pressed = true; 103 | } 104 | 105 | void VizHandle::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) { 106 | QGraphicsRectItem::mouseReleaseEvent(event); 107 | 108 | QPointF displacement = pos() - m_pressPos; 109 | emit hasMoved(this, displacement); 110 | } 111 | 112 | void VizHandle::mouseMoveEvent(QGraphicsSceneMouseEvent *event) { 113 | QGraphicsRectItem::mouseMoveEvent(event); 114 | if (m_pressed) { 115 | QPointF displacement = pos() - m_pressPos; 116 | if (!displacement.isNull()) { 117 | emit moving(this, displacement); 118 | } 119 | } 120 | } 121 | 122 | void VizHandle::hoverEnterEvent(QGraphicsSceneHoverEvent *event) { 123 | QGraphicsRectItem::hoverEnterEvent(event); 124 | setBrush(Qt::white); 125 | } 126 | 127 | void VizHandle::hoverLeaveEvent(QGraphicsSceneHoverEvent *event) { 128 | QGraphicsRectItem::hoverLeaveEvent(event); 129 | setBrush(Qt::black); 130 | } 131 | 132 | void VizHandle::startFollowing(const VizHandle * const handle) { 133 | Q_UNUSED(handle); 134 | m_originalPos = pos(); 135 | } 136 | 137 | void VizHandle::connectHandles(QList &list) { 138 | for (VizHandle *v1 : list) { 139 | for (VizHandle *v2 : list) { 140 | if (v1 == v2 || VizHandle::updates[v1->m_kind][v2->m_kind] == NO_UPDATE) 141 | continue; 142 | connect(v1, &VizHandle::aboutToMove, v2, &VizHandle::startFollowing); 143 | connect(v1, &VizHandle::moving, v2, &VizHandle::follow); 144 | } 145 | } 146 | } 147 | 148 | void VizHandle::follow(const VizHandle * const handle, QPointF displacement) { 149 | int updateFlags = VizHandle::updates[handle->kind()][kind()]; 150 | QPointF newPos = m_originalPos; 151 | 152 | if (updateFlags & HORIZONTAL_FULL) { 153 | newPos.rx() += displacement.x(); 154 | } else if (updateFlags & HORIZONTAL_HALF) { 155 | newPos.rx() += displacement.x() / 2; 156 | } 157 | 158 | if (updateFlags & VERTICAL_FULL) { 159 | newPos.ry() += displacement.y(); 160 | } else if (updateFlags & VERTICAL_HALF) { 161 | newPos.ry() += displacement.y() / 2; 162 | } 163 | setPos(newPos); 164 | } 165 | -------------------------------------------------------------------------------- /vizhandle.h: -------------------------------------------------------------------------------- 1 | #ifndef VIZHANDLE_H 2 | #define VIZHANDLE_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | class VizHandle : public QObject, public QGraphicsRectItem { 9 | Q_OBJECT 10 | public: 11 | enum Kind { 12 | LEFT = 0, 13 | RIGHT, 14 | TOP, 15 | BOTTOM, 16 | TOPLEFT, 17 | TOPRIGHT, 18 | BOTTOMLEFT, 19 | BOTTOMRIGHT, 20 | NB_KINDS 21 | }; 22 | 23 | VizHandle(QGraphicsItem *item, Kind kind); 24 | 25 | Kind kind() const { 26 | return m_kind; 27 | } 28 | 29 | static QList createCornerHandles(QGraphicsItem *item) { 30 | QList list; 31 | createCornerHandlesInternal(list, item); 32 | connectHandles(list); 33 | return list; 34 | } 35 | 36 | static QList createCenterHandles(QGraphicsItem *item) { 37 | QList list; 38 | createCenterHandlesInternal(list, item); 39 | connectHandles(list); 40 | return list; 41 | } 42 | 43 | static QList createCenterCornerHandles(QGraphicsItem *item) { 44 | QList list; 45 | createCenterHandlesInternal(list, item); 46 | createCornerHandlesInternal(list, item); 47 | connectHandles(list); 48 | return list; 49 | } 50 | 51 | bool isModifierPressed() const { 52 | return m_modifier; 53 | } 54 | 55 | void recomputePos(); 56 | 57 | void mousePressEvent(QGraphicsSceneMouseEvent *event); 58 | void mouseMoveEvent(QGraphicsSceneMouseEvent *event); 59 | void mouseReleaseEvent(QGraphicsSceneMouseEvent *event); 60 | 61 | void hoverEnterEvent(QGraphicsSceneHoverEvent *event); 62 | void hoverLeaveEvent(QGraphicsSceneHoverEvent *event); 63 | 64 | protected: 65 | QVariant itemChange(GraphicsItemChange change, const QVariant &value); 66 | 67 | signals: 68 | void aboutToMove(const VizHandle *const handle); 69 | void moving(const VizHandle *const handle, QPointF displacement); 70 | void hasMoved(const VizHandle *const handle, QPointF displacement); 71 | 72 | private slots: 73 | void startFollowing(const VizHandle *const handle); 74 | void follow(const VizHandle *const handle, QPointF displacement); 75 | 76 | private: 77 | Kind m_kind; 78 | double m_size = 6; // FIXME: hardcode, take from vizproperties 79 | 80 | QPointF m_pressPos = QPointF(); 81 | bool m_pressed = false; 82 | bool m_modifier = false; 83 | 84 | QPointF m_originalPos; 85 | 86 | enum UpdateFlags { 87 | NO_UPDATE = 0x0, 88 | HORIZONTAL_HALF = 0x1, 89 | HORIZONTAL_FULL = 0x2, 90 | VERTICAL_HALF = 0x4, 91 | VERTICAL_FULL = 0x8 92 | }; 93 | 94 | #define HOR_F_VER_H (HORIZONTAL_FULL | VERTICAL_HALF) 95 | #define HOR_H_VER_F (HORIZONTAL_HALF | VERTICAL_FULL) 96 | // LEFT RIGHT TOP BOTTOM TOPLEFT TOPRIGHT BOTTOMLEFT BOTTOMRIGHT [v from][< to] 97 | constexpr static int updates[NB_KINDS][NB_KINDS] = { 98 | {NO_UPDATE, NO_UPDATE, HORIZONTAL_HALF, HORIZONTAL_HALF, HORIZONTAL_FULL, NO_UPDATE, HORIZONTAL_FULL, NO_UPDATE}, // LEFT 99 | {NO_UPDATE, NO_UPDATE, HORIZONTAL_HALF, HORIZONTAL_HALF, NO_UPDATE, HORIZONTAL_FULL, NO_UPDATE, HORIZONTAL_FULL}, // RIGHT 100 | {VERTICAL_HALF, VERTICAL_HALF, NO_UPDATE, NO_UPDATE, VERTICAL_FULL, VERTICAL_FULL, NO_UPDATE, NO_UPDATE}, // TOP 101 | {VERTICAL_HALF, VERTICAL_HALF, NO_UPDATE, NO_UPDATE, NO_UPDATE, NO_UPDATE, VERTICAL_FULL, VERTICAL_FULL}, // BOTTOM 102 | {HOR_F_VER_H, VERTICAL_HALF, HOR_H_VER_F, HORIZONTAL_HALF, NO_UPDATE, VERTICAL_FULL, HORIZONTAL_FULL, NO_UPDATE}, // TOPLEFT 103 | {VERTICAL_HALF, HOR_F_VER_H, HOR_H_VER_F, HORIZONTAL_HALF, VERTICAL_FULL, NO_UPDATE, NO_UPDATE, HORIZONTAL_FULL}, // TOPRIGHT 104 | {HOR_F_VER_H, VERTICAL_HALF, HORIZONTAL_HALF, HOR_H_VER_F, HORIZONTAL_FULL, NO_UPDATE, NO_UPDATE, VERTICAL_FULL}, // BOTTOMLEFT 105 | {VERTICAL_HALF, HOR_F_VER_H, HORIZONTAL_HALF, HOR_H_VER_F, NO_UPDATE, HORIZONTAL_FULL, VERTICAL_FULL, NO_UPDATE} // BOTTOMRIGHT 106 | }; 107 | #undef HOR_F_VER_H 108 | #undef HOR_H_VER_F 109 | 110 | static void connectHandles(QList &list); 111 | 112 | static void createCornerHandlesInternal(QList &list, QGraphicsItem *item) { 113 | list.append(new VizHandle(item, Kind::TOPLEFT)); 114 | list.append(new VizHandle(item, Kind::TOPRIGHT)); 115 | list.append(new VizHandle(item, Kind::BOTTOMLEFT)); 116 | list.append(new VizHandle(item, Kind::BOTTOMRIGHT)); 117 | } 118 | 119 | static void createCenterHandlesInternal(QList &list, QGraphicsItem *item) { 120 | list.append(new VizHandle(item, Kind::LEFT)); 121 | list.append(new VizHandle(item, Kind::RIGHT)); 122 | list.append(new VizHandle(item, Kind::TOP)); 123 | list.append(new VizHandle(item, Kind::BOTTOM)); 124 | } 125 | }; 126 | 127 | #endif // VIZHANDLE_H 128 | -------------------------------------------------------------------------------- /vizmanipulationmanager.h: -------------------------------------------------------------------------------- 1 | #ifndef VIZMANIPULATIONMANAGER_H 2 | #define VIZMANIPULATIONMANAGER_H 3 | 4 | #include 5 | #include 6 | 7 | class VizPolyhedron; 8 | class VizPoint; 9 | class VizCoordinateSystem; 10 | 11 | struct TransformationGroup; 12 | 13 | class ClintScop; 14 | 15 | class VizManipulationManager : public QObject { 16 | Q_OBJECT 17 | public: 18 | explicit VizManipulationManager(QObject *parent = 0); 19 | 20 | void rearrangePiles2D(std::vector &createdBeta, bool pileDeleted, TransformationGroup &group, int pileIdx, size_t pileNb); 21 | void rearrangeCSs2D(int coordinateSystemIdx, bool csDeleted, std::vector &createdBeta, size_t pileSize, TransformationGroup &group); 22 | 23 | enum Dir { 24 | LEFT, 25 | RIGHT, 26 | UP, 27 | DOWN 28 | }; 29 | 30 | enum Corner { 31 | C_BOTTOM = 0x1, // TOP = ~BOTTOM 32 | C_RIGHT = 0x2, // LEFT = ~RIGHT 33 | }; 34 | enum { 35 | C_LEFT = 0x0 36 | }; 37 | enum { 38 | C_TOP = 0x0 39 | }; 40 | 41 | int rotationCase(); 42 | signals: 43 | void intentionMoveHorizontally(int amount); 44 | void intentionMoveVertically(int amount); 45 | void movedHorizontally(int amount); 46 | void movedVertically(int amount); 47 | 48 | public slots: 49 | void polyhedronAboutToMove(VizPolyhedron *polyhedron); 50 | void polyhedronMoving(VizPolyhedron *polyhedron, QPointF displacement); 51 | void polyhedronHasMoved(VizPolyhedron *polyhedron); 52 | 53 | void polyhedronAboutToDetach(VizPolyhedron *polyhedron); 54 | void polyhedronDetaching(QPointF position); 55 | void polyhedronHasDetached(VizPolyhedron *polyhedron); 56 | 57 | void pointAboutToMove(VizPoint *point); 58 | void pointMoving(QPointF position); 59 | void pointHasMoved(VizPoint *point); 60 | 61 | void pointRightClicked(VizPoint *point); 62 | 63 | void polyhedronAboutToResize(VizPolyhedron *polyhedron, Dir direction); 64 | void polyhedronResizing(QPointF displacement); 65 | void polyhedronHasResized(VizPolyhedron *polyhedron); 66 | void polyhedronHasCreatedDimension(VizPolyhedron *polyhedron); 67 | 68 | void polyhedronAboutToSkew(VizPolyhedron *polyhedron, int corner); 69 | void polyhedronSkewing(QPointF displacement); 70 | void polyhedronHasSkewed(VizPolyhedron *polyhedron); 71 | 72 | void polyhedronAboutToRotate(VizPolyhedron *polyhedron, int corner); 73 | void polyhedronRotating(QPointF displacement); 74 | void polyhedronHasRotated(VizPolyhedron *polyhedron); 75 | 76 | private: 77 | VizPolyhedron *m_polyhedron = nullptr; 78 | VizPoint *m_point = nullptr; 79 | VizCoordinateSystem *m_coordinateSystem = nullptr; 80 | 81 | int m_initCSHorizontalMin, m_initCSVerticalMin; 82 | 83 | int m_horzOffset, m_vertOffset; 84 | bool m_detached; 85 | bool m_firstMovement = false; 86 | Dir m_direction; 87 | int m_corner; 88 | double m_rotationAngle; 89 | bool m_skewing = false; 90 | bool m_resizing = false; 91 | int m_creatingDimension = 0; 92 | 93 | enum { 94 | PT_NODETACH, 95 | PT_DETACH_HORIZONTAL, 96 | PT_DETACH_VERTICAL, 97 | PT_DETACHED_HORIZONTAL, 98 | PT_DETACHED_VERTICAL, 99 | PT_ATTACH, 100 | PT_ATTACHED 101 | } m_pointDetachState; 102 | int m_pointDetachValue; 103 | bool m_pointDetachLast; 104 | 105 | void ensureTargetConsistency(); 106 | 107 | bool isFlagSet(int flags, int flag) { 108 | if (flag == 0) { 109 | return (~flags) & flag; 110 | } 111 | return flags & flag; 112 | } 113 | 114 | void remapBetas(TransformationGroup group, ClintScop *scop); 115 | }; 116 | 117 | #endif // VIZMANIPULATIONMANAGER_H 118 | -------------------------------------------------------------------------------- /vizpoint.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "vizpoint.h" 4 | #include "vizprojection.h" 5 | 6 | const int VizPoint::NO_COORD; 7 | 8 | VizPoint::VizPoint(VizPolyhedron *polyhedron) : 9 | QGraphicsObject(polyhedron), m_polyhedron(polyhedron) { 10 | 11 | setFlag(QGraphicsItem::ItemIsSelectable); 12 | setFlag(QGraphicsItem::ItemIsMovable); 13 | setFlag(QGraphicsItem::ItemSendsGeometryChanges); 14 | 15 | if (m_polyhedron) { 16 | VizProperties *props = m_polyhedron->coordinateSystem()->projection()->vizProperties(); 17 | if (props->filledPoints() && m_polyhedron->occurrence()) { 18 | setColor(props->color(m_polyhedron->occurrence()->betaVector())); 19 | } else { 20 | setColor(QColor::fromRgb(100, 100, 100, 127)); 21 | } 22 | } 23 | } 24 | 25 | void VizPoint::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) { 26 | Q_UNUSED(widget); 27 | painter->save(); 28 | const double radius = 29 | m_polyhedron->coordinateSystem()->projection()->vizProperties()->pointRadius(); 30 | if (option->state & QStyle::State_Selected) 31 | painter->setBrush(QBrush(Qt::white)); 32 | else 33 | painter->setBrush(QBrush(m_color)); 34 | painter->drawEllipse(QPointF(0, 0), radius, radius); 35 | painter->restore(); 36 | } 37 | 38 | QRectF VizPoint::boundingRect() const { 39 | const double radius = 40 | m_polyhedron->coordinateSystem()->projection()->vizProperties()->pointRadius(); 41 | return QRectF(-radius, -radius, 2*radius, 2*radius); 42 | } 43 | 44 | QPainterPath VizPoint::shape() const { 45 | QPainterPath path; 46 | path.addEllipse(boundingRect()); 47 | return path; 48 | } 49 | 50 | QVariant VizPoint::itemChange(GraphicsItemChange change, const QVariant &value) { 51 | if (change == QGraphicsItem::ItemSelectedHasChanged) { 52 | coordinateSystem()->projection()->selectionManager()->pointSelectionChanged(this, value.toBool()); 53 | } else if (change == QGraphicsItem::ItemPositionHasChanged) { 54 | emit positionChanged(); 55 | } 56 | return QGraphicsItem::itemChange(change, value); 57 | } 58 | 59 | void VizPoint::mousePressEvent(QGraphicsSceneMouseEvent *event) { 60 | if (coordinateSystem()->projection()->selectionManager()->selectedPoints().empty()) { 61 | polyhedron()->mousePressEvent(event); 62 | return; 63 | } 64 | polyhedron()->hideHandles(); 65 | 66 | if (event->button() == Qt::RightButton) { 67 | coordinateSystem()->projection()->manipulationManager()->pointRightClicked(this); 68 | return; 69 | } 70 | 71 | QGraphicsItem::mousePressEvent(event); 72 | m_pressPos = pos(); 73 | coordinateSystem()->projection()->manipulationManager()->pointAboutToMove(this); 74 | } 75 | 76 | void VizPoint::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) { 77 | if (coordinateSystem()->projection()->selectionManager()->selectedPoints().empty()) { 78 | polyhedron()->mouseReleaseEvent(event); 79 | return; 80 | } 81 | QGraphicsItem::mouseReleaseEvent(event); 82 | m_pressPos = QPointF(0,0); 83 | coordinateSystem()->projection()->manipulationManager()->pointHasMoved(this); 84 | } 85 | 86 | void VizPoint::mouseMoveEvent(QGraphicsSceneMouseEvent *event) { 87 | if (coordinateSystem()->projection()->selectionManager()->selectedPoints().empty()) { 88 | polyhedron()->mouseMoveEvent(event); 89 | return; 90 | } 91 | QGraphicsItem::mouseMoveEvent(event); 92 | QPointF diff = pos() - m_pressPos; 93 | coordinateSystem()->projection()->manipulationManager()->pointMoving(diff); 94 | } 95 | 96 | void VizPoint::setScatteredCoordinates(int horizontal, int vertical) { 97 | m_scatteredHorizontal = horizontal; 98 | m_scatteredVertical = vertical; 99 | } 100 | 101 | ClintStmt *VizPoint::statement() const { 102 | return m_polyhedron->statement(); 103 | } 104 | 105 | ClintScop *VizPoint::scop() const { 106 | return m_polyhedron->scop(); 107 | } 108 | 109 | ClintProgram *VizPoint::program() const { 110 | return m_polyhedron->program(); 111 | } 112 | 113 | VizCoordinateSystem *VizPoint::coordinateSystem() const { 114 | return m_polyhedron->coordinateSystem(); 115 | } 116 | -------------------------------------------------------------------------------- /vizpoint.h: -------------------------------------------------------------------------------- 1 | #ifndef VIZPOINT_H 2 | #define VIZPOINT_H 3 | 4 | #include 5 | #include 6 | 7 | #include "vizpolyhedron.h" 8 | #include "vizcoordinatesystem.h" 9 | #include "clintprogram.h" 10 | #include "clintscop.h" 11 | #include "clintstmt.h" 12 | 13 | class VizPoint : public QGraphicsObject 14 | { 15 | Q_OBJECT 16 | public: 17 | const static int NO_COORD = INT_MAX; 18 | 19 | explicit VizPoint(VizPolyhedron *polyhedron); 20 | 21 | VizPolyhedron *polyhedron() const { 22 | return m_polyhedron; 23 | } 24 | 25 | ClintStmt *statement() const; 26 | ClintScop *scop() const; 27 | ClintProgram *program() const; 28 | VizCoordinateSystem *coordinateSystem() const; 29 | 30 | void setScatteredCoordinates(int horizontal = NO_COORD, int vertical = NO_COORD); 31 | 32 | void setOriginalCoordinates(const std::vector &coordinates) { 33 | m_originalCoordinates = coordinates; 34 | } 35 | 36 | void setScatteredCoordinates(const std::pair &coordinates) { 37 | setScatteredCoordinates(coordinates.first, coordinates.second); 38 | } 39 | 40 | const std::vector &originalCoordinates() const { 41 | return m_originalCoordinates; 42 | } 43 | 44 | std::pair scatteredCoordinates() const { 45 | return std::move(std::make_pair(m_scatteredHorizontal, m_scatteredVertical)); 46 | } 47 | 48 | void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); 49 | QRectF boundingRect() const; 50 | QPainterPath shape() const; 51 | QVariant itemChange(GraphicsItemChange change, const QVariant &value); 52 | 53 | void setColor(QColor color) { 54 | m_color = color; 55 | } 56 | 57 | void reparent(VizPolyhedron *parent) { 58 | if (parent == m_polyhedron) 59 | return; 60 | m_polyhedron = parent; 61 | QPointF pos = scenePos(); 62 | setParentItem(parent); 63 | setPos(parent->mapFromScene(pos)); 64 | } 65 | 66 | signals: 67 | void positionChanged(); 68 | 69 | public slots: 70 | 71 | public: 72 | void mousePressEvent(QGraphicsSceneMouseEvent *event); 73 | void mouseMoveEvent(QGraphicsSceneMouseEvent *event); 74 | void mouseReleaseEvent(QGraphicsSceneMouseEvent *event); 75 | 76 | private: 77 | VizPolyhedron *m_polyhedron; 78 | // These coordinates do not define point position on the coordinate system 79 | // or in the polyhedron. The position is relative to the axes intersection 80 | // and minima of the point coordinates in the polyhedron. 81 | std::vector m_originalCoordinates; 82 | int m_scatteredHorizontal = NO_COORD; 83 | int m_scatteredVertical = NO_COORD; 84 | 85 | bool m_selectionChangeBarrier = false; 86 | 87 | QColor m_color; 88 | QPointF m_pressPos; 89 | }; 90 | 91 | #endif // VIZPOINT_H 92 | -------------------------------------------------------------------------------- /vizpolyhedron.h: -------------------------------------------------------------------------------- 1 | #ifndef VIZPOLYHEDRON_H 2 | #define VIZPOLYHEDRON_H 3 | 4 | #include "clintprogram.h" 5 | #include "clintscop.h" 6 | #include "clintstmt.h" 7 | #include "clintstmtoccurrence.h" 8 | #include "vizcoordinatesystem.h" 9 | #include "vizhandle.h" 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | #include 17 | 18 | #include 19 | 20 | class VizPoint; 21 | class VizDepArrow; 22 | 23 | class VizPolyhedron : public QGraphicsObject { 24 | Q_OBJECT 25 | public: 26 | explicit VizPolyhedron(ClintStmtOccurrence *occurrence, VizCoordinateSystem *vcs); 27 | ~VizPolyhedron(); 28 | 29 | ClintStmtOccurrence *occurrence() const { 30 | return m_occurrence; 31 | } 32 | 33 | ClintStmt *statement() const { 34 | return m_occurrence->statement(); 35 | } 36 | 37 | VizCoordinateSystem *coordinateSystem() const { 38 | return m_coordinateSystem; 39 | } 40 | 41 | ClintScop *scop() const { 42 | return m_occurrence->scop(); 43 | } 44 | 45 | ClintProgram *program() const { 46 | return m_occurrence->program(); 47 | } 48 | 49 | int localHorizontalMin() const { 50 | return m_localHorizontalMin; 51 | } 52 | 53 | int localVerticalMin() const { 54 | return m_localVerticalMin; 55 | } 56 | 57 | int localHorizontalMax() const { 58 | return m_localHorizontalMax; 59 | } 60 | 61 | int localVerticalMax() const { 62 | return m_localVerticalMax; 63 | } 64 | 65 | void recomputeMinMax(); 66 | 67 | void setInternalDependences(std::vector> &&dependences); 68 | void resetPointPositions(); 69 | 70 | void reparent(VizCoordinateSystem *vcs) { 71 | if (vcs == m_coordinateSystem) 72 | return; 73 | m_coordinateSystem = vcs; 74 | QPointF scenePosition = scenePos(); 75 | setParentItem(vcs); 76 | setPos(vcs->mapFromScene(scenePosition)); 77 | } 78 | 79 | void setOverrideSetPos(bool value = true) { 80 | m_overrideSetPos = value; 81 | } 82 | 83 | void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); 84 | QRectF boundingRect() const; 85 | QPainterPath shape() const; 86 | QVariant itemChange(GraphicsItemChange change, const QVariant &value); 87 | void mousePressEvent(QGraphicsSceneMouseEvent *event); 88 | void mouseMoveEvent(QGraphicsSceneMouseEvent *event); 89 | void mouseReleaseEvent(QGraphicsSceneMouseEvent *event); 90 | void hoverEnterEvent(QGraphicsSceneHoverEvent *event); 91 | void hoverLeaveEvent(QGraphicsSceneHoverEvent *event); 92 | 93 | QColor color() const { 94 | return m_backgroundColor; 95 | } 96 | 97 | void setColor(QColor clr) { 98 | m_backgroundColor = clr; 99 | update(); 100 | } 101 | 102 | void setPos(const QPointF &position) { 103 | if (m_overrideSetPos) { 104 | m_pressPos = position; 105 | } else { 106 | QGraphicsObject::setPos(position); 107 | } 108 | } 109 | void setPos(qreal x, qreal y) { 110 | setPos(QPointF(x, y)); 111 | } 112 | 113 | VizPoint *point(const std::vector &originalCoordinates) const; 114 | std::unordered_set points() const; 115 | 116 | void reparentPoint(VizPoint *point); 117 | bool hasPoints() const; 118 | 119 | void updateShape() { 120 | recomputeMinMax(); 121 | recomputeShape(); 122 | resetPointPositions(); 123 | } 124 | 125 | void updateInternalDependences(); 126 | 127 | void setOccurrenceSilent(ClintStmtOccurrence *occurrence); 128 | 129 | void hideHandles() { 130 | setHandleVisible(false); 131 | m_hovered = false; 132 | } 133 | 134 | void prepareExtendRight(double extra); 135 | void prepareExtendLeft(double extra); 136 | void prepareExtendUp(double extra); 137 | void prepareExtendDown(double extra); 138 | 139 | void prepareSkewHorizontalTop(double offset); 140 | void prepareSkewHorizontalBottom(double offset); 141 | void prepareSkewVerticalLeft(double offset); 142 | void prepareSkewVerticalRight(double offset); 143 | 144 | double prepareRotate(QPointF displacement); 145 | void resetRotate(); 146 | 147 | void prepareRotateAngle(double angle); 148 | 149 | void debugPrintPoints(); 150 | signals: 151 | void positionChanged(); 152 | 153 | public slots: 154 | void occurrenceChanged(); 155 | void handleMoving(const VizHandle *const handle, QPointF displacement); 156 | void handleAboutToMove(const VizHandle *const handle); 157 | void handleHasMoved(const VizHandle *const handle, QPointF displacement); 158 | 159 | void occurrenceDeleted(); 160 | 161 | private: 162 | ClintStmtOccurrence *m_occurrence = nullptr; 163 | VizCoordinateSystem *m_coordinateSystem; 164 | QPainterPath m_polyhedronShape; 165 | QColor m_backgroundColor; 166 | 167 | std::vector m_handles; 168 | bool m_hovered = false; 169 | QPainterPath m_originalPolyhedronShape; 170 | 171 | std::vector m_tileLines; 172 | 173 | // Mapping from 2D original coordinates to all points in the projection with these original coordinates. 174 | typedef std::unordered_map, VizPoint *, boost::hash>> PointMap; 175 | PointMap m_pts; 176 | PointMap m_pointOthers; /// Points with original coordinates different than those in m_pts, projected at the same position. 177 | void reprojectPoints(); 178 | 179 | std::unordered_set m_deps; 180 | int m_localHorizontalMin = 0; 181 | int m_localVerticalMin = 0; 182 | int m_localHorizontalMax = 0; 183 | int m_localVerticalMax = 0; 184 | 185 | bool m_selectionChangeBarrier = false; 186 | 187 | bool m_wasPressed = false; 188 | bool m_wasShiftPressed = false; 189 | bool m_overrideSetPos = false; 190 | QPointF m_pressPos; 191 | 192 | QPointF m_rotationCenter; 193 | 194 | bool m_mouseEventForwarding = false; 195 | 196 | void setPointVisiblePos(VizPoint *vp, int x, int y); 197 | static std::pair pointScatteredCoordsReal(const VizPoint *vp); 198 | std::vector convexHull() const; 199 | QPolygonF computePolygon() const; 200 | void recomputeShape(); 201 | 202 | void updateHandlePositions(); 203 | void setHandleVisible(bool visible = true); 204 | 205 | QPointF mapToCoordinates(double x, double y) const; 206 | 207 | QPointF mapToCoordinates(std::pair coords) const { 208 | return mapToCoordinates(coords.first, coords.second); 209 | } 210 | 211 | QPointF mapToCoordinates(VizPoint *vp) const { 212 | return mapToCoordinates(pointScatteredCoordsReal(vp)); 213 | } 214 | void disconnectAll(); 215 | }; 216 | 217 | #endif // VIZPOLYHEDRON_H 218 | -------------------------------------------------------------------------------- /vizprojection.h: -------------------------------------------------------------------------------- 1 | #ifndef VIZPROJECTION_H 2 | #define VIZPROJECTION_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | 10 | #include "projectionview.h" 11 | #include "vizcoordinatesystem.h" 12 | #include "vizmanipulationmanager.h" 13 | #include "vizproperties.h" 14 | #include "vizselectionmanager.h" 15 | 16 | class VizProjection : public QObject 17 | { 18 | Q_OBJECT 19 | public: 20 | VizProjection(int horizontalDimensionIdx, int verticalDimensionIdx, QObject *parent = 0); 21 | QWidget *widget() { 22 | return m_view; 23 | } 24 | 25 | void projectScop(ClintScop *vscop); 26 | 27 | /*inline*/ VizProperties *vizProperties() const { 28 | return m_vizProperties; 29 | } 30 | 31 | /*inline*/ VizSelectionManager *selectionManager() const { 32 | return m_selectionManager; 33 | } 34 | 35 | /*inline*/ VizManipulationManager *manipulationManager() const { 36 | return m_manipulationManager; 37 | } 38 | 39 | void updateColumnHorizontalMinMax(VizCoordinateSystem *coordinateSystem, int minOffset, int maxOffset); 40 | void ensureFitsHorizontally(VizCoordinateSystem *coordinateSystem, int minimum, int maximum); 41 | void ensureFitsVertically(VizCoordinateSystem *coordinateSystem, int minimum, int maximum); 42 | 43 | int horizontalDimensionIdx() const { 44 | return m_horizontalDimensionIdx; 45 | } 46 | 47 | int verticalDimensionIdx() const { 48 | return m_verticalDimensionIdx; 49 | } 50 | 51 | enum class IsCsAction { Found, InsertPile, InsertCS }; 52 | 53 | class IsCsResult { 54 | public: 55 | IsCsAction action() const { 56 | return m_action; 57 | } 58 | size_t pileIdx() const { 59 | return m_pile; 60 | } 61 | size_t coordinateSystemIdx() const { 62 | return m_coordinateSystem; 63 | } 64 | VizCoordinateSystem *coordinateSystem() const { 65 | return m_vcs; 66 | } 67 | 68 | void setFound(VizCoordinateSystem *cs) { 69 | if (m_action == IsCsAction::InsertPile) { 70 | m_coordinateSystem = 0; 71 | } 72 | m_action = IsCsAction::Found; 73 | m_vcs = cs; 74 | } 75 | 76 | private: 77 | size_t m_pile; // in case InsertPile, insert before this index; if index >= size, insert after the last; in case InsertCS, index of the pile to insert to 78 | size_t m_coordinateSystem; 79 | IsCsAction m_action; 80 | VizCoordinateSystem *m_vcs = nullptr; 81 | 82 | friend class VizProjection; 83 | }; 84 | 85 | VizProjection::IsCsResult isCoordinateSystem(QPointF point); 86 | VizCoordinateSystem *ensureCoordinateSystem(IsCsResult &csAt, int dimensionality); 87 | VizCoordinateSystem *createCoordinateSystem(int dimensionality); 88 | void deleteCoordinateSystem(VizCoordinateSystem *vcs); 89 | 90 | void paintProjection(QPainter *painter) { 91 | m_scene->render(painter); 92 | } 93 | 94 | QSize projectionSize() const { 95 | return m_scene->itemsBoundingRect().size().toSize(); 96 | } 97 | 98 | std::pair csIndices(VizCoordinateSystem *vcs) const; 99 | size_t pileCSNumber(size_t pileIndex) const { 100 | CLINT_ASSERT(pileIndex < m_coordinateSystems.size(), "Pile index out of range"); 101 | return m_coordinateSystems.at(pileIndex).size(); 102 | } 103 | size_t pileNumber() const { 104 | return m_coordinateSystems.size(); 105 | } 106 | 107 | VizCoordinateSystem *insertPile(IsCsResult csAt, int dimensionality); 108 | VizCoordinateSystem *insertCs(IsCsResult csAt, int dimensionality); 109 | void updateOuterDependences(); 110 | void updateInnerDependences(); 111 | void updateInternalDependences(); 112 | 113 | void setViewActive(bool active) { 114 | if (m_view) 115 | m_view->setActive(active); 116 | } 117 | 118 | bool isViewActive() const { 119 | return m_view && m_view->isActive(); 120 | } 121 | 122 | signals: 123 | void selected(int horizontal, int vertical); 124 | 125 | public slots: 126 | void updateProjection(); 127 | void selectProjection(); 128 | 129 | private: 130 | ProjectionView *m_view; 131 | QGraphicsScene *m_scene; 132 | VizProperties *m_vizProperties; 133 | 134 | // Outer index = column index; 135 | // Inner index = row index within the given column 136 | // Different columns may have different number of rows. 137 | std::vector> m_coordinateSystems; 138 | int m_horizontalDimensionIdx; 139 | int m_verticalDimensionIdx; 140 | 141 | VizSelectionManager *m_selectionManager; 142 | VizManipulationManager *m_manipulationManager; 143 | 144 | void appendCoordinateSystem(int dimensionality); 145 | void updateSceneLayout(); 146 | }; 147 | 148 | #endif // VIZPROJECTION_H 149 | -------------------------------------------------------------------------------- /vizproperties.cpp: -------------------------------------------------------------------------------- 1 | #include "macros.h" 2 | #include "vizproperties.h" 3 | 4 | #include 5 | 6 | const size_t VizProperties::NO_DIMENSION; 7 | const size_t VizProperties::UNDEFINED_DIMENSION; 8 | 9 | VizProperties::VizProperties(QObject *parent) : 10 | QObject(parent) { 11 | } 12 | 13 | void VizProperties::setPolyhedronOffset(double offset) { 14 | m_polyhedronOffset = offset; 15 | emit vizPropertyChanged(); 16 | } 17 | 18 | void VizProperties::setPointRadius(double radius) { 19 | m_pointRadius = radius; 20 | emit vizPropertyChanged(); 21 | } 22 | 23 | void VizProperties::setPointDistance(double distance) { 24 | m_pointDistance = distance; 25 | emit vizPropertyChanged(); 26 | } 27 | 28 | void VizProperties::setCoordinateSystemMargin(double margin) { 29 | m_coordinateSystemMargin = margin; 30 | emit vizPropertyChanged(); 31 | } 32 | 33 | QDomElement VizProperties::toXML(QDomDocument &doc) const { 34 | QDomElement element = doc.createElement("vizproperties"); 35 | element.setAttribute("polyhedronOffset", m_polyhedronOffset); 36 | element.setAttribute("pointRadius", m_pointRadius); 37 | element.setAttribute("pointDistance", m_pointDistance); 38 | element.setAttribute("coordinateSystemMargin", m_coordinateSystemMargin); 39 | return element; 40 | } 41 | 42 | void VizProperties::fromXML(const QDomElement &element) { 43 | CLINT_ASSERT(element.tagName() == "vizproperties", "Wrong XML element given"); 44 | QString polyhedronOffsetString = element.attribute("polyhedronOffset"); 45 | QString pointRadiusString = element.attribute("pointRadius"); 46 | QString pointDistanceString = element.attribute("pointDistance"); 47 | QString coordinateSystemMarginString = element.attribute("coordinateSystemMargin"); 48 | bool ok = true; 49 | m_polyhedronOffset = polyhedronOffsetString.toDouble(&ok); 50 | m_pointRadius = pointRadiusString.toDouble(&ok); 51 | m_pointDistance = pointDistanceString.toDouble(&ok); 52 | m_coordinateSystemMargin = coordinateSystemMarginString.toDouble(&ok); 53 | CLINT_ASSERT(ok, "Could not find or interpret one of the viz properties"); 54 | } 55 | -------------------------------------------------------------------------------- /vizproperties.h: -------------------------------------------------------------------------------- 1 | #ifndef VIZPROPERTIES_H 2 | #define VIZPROPERTIES_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | 10 | class VizProperties : public QObject { 11 | Q_OBJECT 12 | public: 13 | explicit VizProperties(QObject *parent = 0); 14 | /*inline*/ double polyhedronOffset() const { 15 | return m_polyhedronOffset; 16 | } 17 | /*inline*/ double pointRadius() const { 18 | return m_pointRadius; 19 | } 20 | /*inline*/ double pointDistance() const { 21 | return m_pointDistance; 22 | } 23 | /*inline*/ double coordinateSystemMargin() const { 24 | return m_coordinateSystemMargin; 25 | } 26 | 27 | QColor color(const std::vector &beta) const { 28 | int id = 0; 29 | for (int i = 0; i < beta.size(); i++) { 30 | id += beta[i] * pow(10, i % 7); 31 | } 32 | id = id % 24; 33 | id = (id * 7) % 24; // distribute far from each other 34 | return QColor::fromHsv(id * 15, 60, 200, 127); 35 | } 36 | 37 | bool filledPolygons() const { 38 | return m_filledPolygons; 39 | } 40 | 41 | bool filledPoints() const { 42 | return m_filledPoints; 43 | } 44 | 45 | const static size_t UNDEFINED_DIMENSION = (size_t) -1; 46 | const static size_t NO_DIMENSION = (size_t) -2; 47 | 48 | QDomElement toXML(QDomDocument &doc) const; 49 | void fromXML(const QDomElement &xml); 50 | 51 | Q_PROPERTY(double polyhedronOffset 52 | READ polyhedronOffset 53 | WRITE setPolyhedronOffset 54 | NOTIFY vizPropertyChanged) 55 | Q_PROPERTY(double pointRadius 56 | READ pointRadius 57 | WRITE setPointRadius 58 | NOTIFY vizPropertyChanged) 59 | Q_PROPERTY(double pointDistance 60 | READ pointDistance 61 | WRITE setPointDistance 62 | NOTIFY vizPropertyChanged) 63 | Q_PROPERTY(double coordinateSystemMargin 64 | READ coordinateSystemMargin 65 | WRITE setCoordinateSystemMargin 66 | NOTIFY vizPropertyChanged) 67 | 68 | signals: 69 | void vizPropertyChanged(); 70 | 71 | public slots: 72 | void setPolyhedronOffset(double offset); 73 | void setPointRadius(double radius); 74 | void setPointDistance(double distance); 75 | void setCoordinateSystemMargin(double margin); 76 | 77 | private: 78 | double m_polyhedronOffset = 4.0; 79 | double m_pointRadius = 4.0; 80 | double m_pointDistance = 16.0; 81 | double m_coordinateSystemMargin = 5.0; 82 | 83 | bool m_filledPolygons = true; 84 | bool m_filledPoints = false; 85 | }; 86 | 87 | #endif // VIZPROPERTIES_H 88 | -------------------------------------------------------------------------------- /vizselectionmanager.cpp: -------------------------------------------------------------------------------- 1 | #include "vizcoordinatesystem.h" 2 | #include "vizpoint.h" 3 | #include "vizpolyhedron.h" 4 | #include "vizselectionmanager.h" 5 | 6 | #include 7 | #include 8 | 9 | #include 10 | 11 | class BarrierRAII { 12 | public: 13 | explicit BarrierRAII(bool *flag) : m_flagPtr(flag) { 14 | *m_flagPtr = true; 15 | } 16 | 17 | BarrierRAII(const BarrierRAII &) = delete; 18 | 19 | ~BarrierRAII() { 20 | *m_flagPtr = false; 21 | } 22 | 23 | private: 24 | bool *m_flagPtr; 25 | }; 26 | 27 | VizSelectionManager::VizSelectionManager(QObject *parent) : 28 | QObject(parent) { 29 | } 30 | 31 | void VizSelectionManager::polyhedronSelectionChanged(VizPolyhedron *polyhedron, bool selected) { 32 | // Ignore selection changes triggered by the manager itself. 33 | if (m_selectionBarrier) 34 | return; 35 | BarrierRAII ba(&m_selectionBarrier); 36 | (void) ba; 37 | 38 | if (!selected) { 39 | m_selectedPolyhedra.erase(polyhedron); 40 | return; 41 | } 42 | 43 | bool selectionAllowed = true; 44 | if (!m_selectedPoints.empty() || !m_selectedCoordinateSystems.empty()) { 45 | selectionAllowed = resolveTypeConflict(m_selectedPolyhedra, polyhedron); 46 | } 47 | if (!selectionAllowed) 48 | return; 49 | 50 | // Allow multiple selection of polygons from the same coordinate system only. 51 | bool sameCS = std::all_of(std::begin(m_selectedPolyhedra), std::end(m_selectedPolyhedra), 52 | [polyhedron](VizPolyhedron *p) { 53 | return polyhedron->coordinateSystem() == p->coordinateSystem(); 54 | }); 55 | if (!sameCS) { 56 | selectionAllowed = resolveConflict(m_selectedPolyhedra, polyhedron); 57 | } 58 | if (!selectionAllowed) 59 | return; 60 | m_selectedPolyhedra.insert(polyhedron); 61 | emit selectionChanged(); 62 | } 63 | 64 | void VizSelectionManager::pointSelectionChanged(VizPoint *point, bool selected) { 65 | // clearSelection(m_selectedPoints); 66 | // Ignore selection changes triggered by the manager itself. 67 | if (m_selectionBarrier) 68 | return; 69 | BarrierRAII ba(&m_selectionBarrier); 70 | (void) ba; 71 | 72 | if (!selected) { 73 | m_selectedPoints.erase(point); 74 | return; 75 | } 76 | 77 | bool selectionAllowed = true; 78 | if (!m_selectedPolyhedra.empty() || !m_selectedCoordinateSystems.empty()) { 79 | selectionAllowed = resolveTypeConflict(m_selectedPoints, point); 80 | } 81 | if (!selectionAllowed) 82 | return; 83 | m_selectedPoints.insert(point); 84 | emit selectionChanged(); 85 | } 86 | 87 | // Coordinate system selection is not allowed 88 | void VizSelectionManager::coordinateSystemSelectionChanged(VizCoordinateSystem *coordinateSystem, bool selected) { 89 | clearSelection(m_selectedCoordinateSystems); 90 | } 91 | 92 | void VizSelectionManager::clearSelection() { 93 | clearSelection(m_selectedPolyhedra); 94 | clearSelection(m_selectedPoints); 95 | clearSelection(m_selectedCoordinateSystems); 96 | } 97 | 98 | -------------------------------------------------------------------------------- /vizselectionmanager.h: -------------------------------------------------------------------------------- 1 | #ifndef VIZSELECTIONMANAGER_H 2 | #define VIZSELECTIONMANAGER_H 3 | 4 | #include 5 | #include 6 | 7 | #include "macros.h" 8 | 9 | class VizPolyhedron; 10 | class VizPoint; 11 | class VizCoordinateSystem; 12 | 13 | class VizSelectionManager : public QObject { 14 | Q_OBJECT 15 | public: 16 | explicit VizSelectionManager(QObject *parent = 0); 17 | 18 | enum class ConflictPolicy { 19 | KeepOld, 20 | ClearOld 21 | }; 22 | 23 | enum class TypeConflictPolicy { 24 | KeepOld, 25 | AllowMix, 26 | ClearOld 27 | }; 28 | 29 | const std::unordered_set &selectedPolyhedra() const { 30 | return m_selectedPolyhedra; 31 | } 32 | 33 | const std::unordered_set &selectedPoints() const { 34 | return m_selectedPoints; 35 | } 36 | 37 | signals: 38 | void selectionChanged(); 39 | 40 | public slots: 41 | void polyhedronSelectionChanged(VizPolyhedron *polyhedron, bool selected); 42 | void pointSelectionChanged(VizPoint *point, bool selected); 43 | void coordinateSystemSelectionChanged(VizCoordinateSystem *coordinateSystem, bool selected); 44 | void clearSelection(); 45 | 46 | private: 47 | std::unordered_set m_selectedPolyhedra; 48 | std::unordered_set m_selectedPoints; 49 | std::unordered_set m_selectedCoordinateSystems; 50 | 51 | ConflictPolicy m_conflictPolicy = ConflictPolicy::ClearOld; 52 | TypeConflictPolicy m_typeConflictPolicy = TypeConflictPolicy::ClearOld; 53 | 54 | bool m_selectionBarrier = false; 55 | 56 | template 57 | void clearSelection(std::unordered_set &selection) { 58 | for (T *element : selection) { 59 | element->setSelected(false); 60 | } 61 | selection.clear(); 62 | } 63 | 64 | template 65 | bool resolveConflict(std::unordered_set &selection, T *element) { 66 | switch (m_conflictPolicy) { 67 | case ConflictPolicy::ClearOld: 68 | clearSelection(selection); 69 | return true; 70 | break; 71 | case ConflictPolicy::KeepOld: 72 | return false; 73 | break; 74 | } 75 | } 76 | 77 | template 78 | bool resolveTypeConflict(std::unordered_set &selection, T *element) { 79 | switch(m_typeConflictPolicy) { 80 | case TypeConflictPolicy::ClearOld: 81 | clearSelection(); 82 | return true; 83 | break; 84 | case TypeConflictPolicy::AllowMix: 85 | return true; 86 | break; 87 | case TypeConflictPolicy::KeepOld: 88 | return false; 89 | break; 90 | } 91 | } 92 | }; 93 | 94 | #endif // VIZSELECTIONMANAGER_H 95 | --------------------------------------------------------------------------------