diff --git a/.gitignore b/.gitignore index c58f32d..57bc91f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ - -gcc/ *.swp +build/ +gcc/ +tags* diff --git a/.gitmodules b/.gitmodules index 21b9830..71ba810 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,4 +1,5 @@ -[submodule "pdf-generator"] +[submodule "pdf-generator/"] path = pdf-generator - url = https://github.com/mpark/wg21.git branch = master + url = https://github.com/MorTD/wg21 + diff --git a/P2022/Makefile b/P2022/Makefile new file mode 100644 index 0000000..f5cdaef --- /dev/null +++ b/P2022/Makefile @@ -0,0 +1 @@ +include ../pdf-generator/Makefile diff --git a/P2022/P2022R0.md b/P2022/P2022R0.md new file mode 100644 index 0000000..32f2474 --- /dev/null +++ b/P2022/P2022R0.md @@ -0,0 +1,248 @@ + + +--- +title: "Rangified version of lexicographical_compare_three_way" +document: P2794R1 +date: today +audience: + - SG9 + - LEWG +author: + - name: Ran Regev + email: +toc: false +--- + + + + +# Revision History + - R1 + - Added link to github implementation + - Added code example + - R0 + - initial work + +# Motivation and Scope +This document adds the wording for ```ranges::lexicographical_compare_three_way``` + +# Design Decisions + +- We explored the following directions and decided to drop them: + - Having restrictions on the relation between the ranges. We found it unneccessary as the comp predicate glue the ranges together to this comparison's needs. + - Returning not only the comparison result but also the iterators to the ranges where the decision was made (return a result-struct). We couldn't find any useful implementation for these iterators and therefore decided to drop the idea. + +- The chosen direction is as follows: + - Follow the way std::lexicographical_compare_three_way is declared. + - The Comp function is restricted to return one of the comparison categories, and nothing else. Therefore - + - There is no reason to restrict the relation between the compared ranges in any way. + - Functions built on top of ```ranges::lexicographical_compare_three_way``` may restrict their input parameters if required. + - Functions built on top of ```ranges::lexicographical_compare_three_way``` such as (the yet to be defined) ```ranges::sort_three_way()``` should benefit from the additional information that can be found in the return value of ```ranges::lexicographical_compare_three_way```, and even use it to indicate the user that the function ended in a specific state. E.g. sort_three_way() may report that the resulted sorted range is sorted from smallest to largest (or largest to smallest), all element are equal or even that the given range is unsortable. + +# Code Example +- In [@GitHub] branch P2022/master one can build and run [@Tests] to experiment with the function + + +# Proposed Wording + + +## Add to [algorithm.syn] + +> | template +> | constexpr auto +> | lexicographical_compare_three_way(InputIterator1 b1, InputIterator1 e1, +> | InputIterator2 b2, InputIterator2 e2); + +> ::: add +> | template +> | concept same-as-one-of = (same_as or ...); // exposition only +> | +> | template< +> | input_iterator I1, +> | input_iterator I2, +> | class Comp, +> | class Proj1, +> | class Proj2 +> | > +> | using lexicographical-compare-three-way-result-t = +> | invoke_result_t< +> | Comp, +> | typename projected::value_type, +> | typename projected::value_type +> | >; // exposition-only +> | +> | constexpr bool is-lexicographical-compare-three-way-result-ordering = +> | same-as-one-of< +> | lexicographical-compare-three-way-result-t< +> | I1, I2, Comp, Proj1, Proj2 +> | >, +> | strong_ordering, weak_ordering, partial_ordering>; //exposition-only +> | +> | template< +> | input_iterator I1, sentinel_for S1, +> | input_iterator I2, sentinel_for S2, +> | class Comp = compare_three_way, +> | class Proj1 = identity, +> | class Proj2 = identity +> | > +> | requires +> | is-lexicographical-compare-three-way-result-ordering< +> | I1, I2, Comp, Proj1, Proj2 +> | > +> | constexpr auto +> | ranges::lexicographical_compare_three_way( +> | I1 first1, +> | S1 last1, +> | I2 first2, +> | S2 last2, +> | Comp comp = {}, +> | Proj1 proj1 = {}, +> | Proj2 proj2 = {} +> | ) -> common_comparison_category_t< +> | decltype( +> | comp(proj1(\*first1), proj2(\*first2)) +> | ), +> | strong_ordering +> | >; +> | +> | template< +> | ranges::input_range R1, +> | ranges::input_range R2, +> | class Comp = compare_three_way, +> | class Proj1 = identity, +> | class Proj2 = identity +> | > +> | requires +> | is-lexicographical-compare-three-way-result-ordering< +> | iterator_t\, iterator_t\, Comp, Proj1, Proj2 +> | > +> | constexpr auto +> | ranges::lexicographical_compare_three_way( +> | R1&& r1, +> | R2&& r2, +> | Comp comp = {}, +> | Proj1 proj1 = {}, +> | Proj2 proj2 = {} +> | ) -> common_comparison_category_t< +> | decltype( +> | comp(proj1(*ranges::begin(r1)), proj2(*ranges::begin(r2))) +> | ), +> | strong_ordering +> | >; +> ::: + +## Add to §27.8.12 [alg.three.way] + +> | template +> | constexpr auto +> | lexicographical_compare_three_way(InputIterator1 b1, InputIterator1 e1, +> | InputIterator2 b2, InputIterator2 e2); + +> ::: add +> | template +> | concept same-as-one-of = (same_as or ...); // exposition only +> | +> | template< +> | input_iterator I1, +> | input_iterator I2, +> | class Comp, +> | class Proj1, +> | class Proj2 +> | > +> | using lexicographical-compare-three-way-result-t = +> | invoke_result_t< +> | Comp, +> | typename projected::value_type, +> | typename projected::value_type +> | >; // exposition-only +> | +> | constexpr bool is-lexicographical-compare-three-way-result-ordering = +> | same-as-one-of< +> | lexicographical-compare-three-way-result-t< +> | I1, I2, Comp, Proj1, Proj2 +> | >, +> | strong_ordering, weak_ordering, partial_ordering>; //exposition-only +> | +> | template< +> | input_iterator I1, sentinel_for S1, +> | input_iterator I2, sentinel_for S2, +> | class Comp = compare_three_way, +> | class Proj1 = identity, +> | class Proj2 = identity +> | > +> | requires +> | is-lexicographical-compare-three-way-result-ordering< +> | I1, I2, Comp, Proj1, Proj2 +> | > +> | constexpr auto +> | ranges::lexicographical_compare_three_way( +> | I1 first1, +> | S1 last1, +> | I2 first2, +> | S2 last2, +> | Comp comp = {}, +> | Proj1 proj1 = {}, +> | Proj2 proj2 = {} +> | ) -> common_comparison_category_t< +> | decltype( +> | comp(proj1(\*first1), proj2(\*first2)) +> | ), +> | strong_ordering +> | >; +> | +> | template< +> | ranges::input_range R1, +> | ranges::input_range R2, +> | class Comp = compare_three_way, +> | class Proj1 = identity, +> | class Proj2 = identity +> | > +> | requires +> | is-lexicographical-compare-three-way-result-ordering< +> | iterator_t\, iterator_t\, Comp, Proj1, Proj2 +> | > +> | constexpr auto +> | ranges::lexicographical_compare_three_way( +> | R1&& r1, +> | R2&& r2, +> | Comp comp = {}, +> | Proj1 proj1 = {}, +> | Proj2 proj2 = {} +> | ) -> common_comparison_category_t< +> | decltype( +> | comp(proj1(\*ranges::begin(r1)), proj2(\*ranges::begin(r2))) +> | ), +> | strong_ordering +> | >; +> ::: + +- [1]{.pnum} Let N be the minimum integer between distance(first1,s1) and distance(first2,s2). Let E(n) be comp(proj1(*(first1 + n)), proj2(*(first2 + n))). +- [2]{.pnum} Returns: E(i), where i is the smallest integer in [0, N) such that E(i) != 0 is true, or (distance(first1,s1) <=> distance(first2, s2) if no such integer exists. +- [3]{.pnum} Complexity: At most N applications of comp, proj1, proj2. + +--- +references: + - id: GitHub + citation-label: GitHub + title: "implementation" + author: + - family: Regev + given: Ran + URL: https://github.com/regevran/IlPapersFork/tree/P2022/master + + - id: Tests + citation-label: Tests + title: "tests" + author: + - family: Regev + - given: Ran + URL: https://github.com/regevran/IlPapersFork/tree/P2022/master/P2022/tests +--- + + +# Acknowledgements + Alex Dathskovsky + Avi Korzac + Lee-or Saar + Mor Elmaliach + Yaron Meister diff --git a/P2022/P2022R1.md b/P2022/P2022R1.md new file mode 100644 index 0000000..32f2474 --- /dev/null +++ b/P2022/P2022R1.md @@ -0,0 +1,248 @@ + + +--- +title: "Rangified version of lexicographical_compare_three_way" +document: P2794R1 +date: today +audience: + - SG9 + - LEWG +author: + - name: Ran Regev + email: +toc: false +--- + + + + +# Revision History + - R1 + - Added link to github implementation + - Added code example + - R0 + - initial work + +# Motivation and Scope +This document adds the wording for ```ranges::lexicographical_compare_three_way``` + +# Design Decisions + +- We explored the following directions and decided to drop them: + - Having restrictions on the relation between the ranges. We found it unneccessary as the comp predicate glue the ranges together to this comparison's needs. + - Returning not only the comparison result but also the iterators to the ranges where the decision was made (return a result-struct). We couldn't find any useful implementation for these iterators and therefore decided to drop the idea. + +- The chosen direction is as follows: + - Follow the way std::lexicographical_compare_three_way is declared. + - The Comp function is restricted to return one of the comparison categories, and nothing else. Therefore - + - There is no reason to restrict the relation between the compared ranges in any way. + - Functions built on top of ```ranges::lexicographical_compare_three_way``` may restrict their input parameters if required. + - Functions built on top of ```ranges::lexicographical_compare_three_way``` such as (the yet to be defined) ```ranges::sort_three_way()``` should benefit from the additional information that can be found in the return value of ```ranges::lexicographical_compare_three_way```, and even use it to indicate the user that the function ended in a specific state. E.g. sort_three_way() may report that the resulted sorted range is sorted from smallest to largest (or largest to smallest), all element are equal or even that the given range is unsortable. + +# Code Example +- In [@GitHub] branch P2022/master one can build and run [@Tests] to experiment with the function + + +# Proposed Wording + + +## Add to [algorithm.syn] + +> | template +> | constexpr auto +> | lexicographical_compare_three_way(InputIterator1 b1, InputIterator1 e1, +> | InputIterator2 b2, InputIterator2 e2); + +> ::: add +> | template +> | concept same-as-one-of = (same_as or ...); // exposition only +> | +> | template< +> | input_iterator I1, +> | input_iterator I2, +> | class Comp, +> | class Proj1, +> | class Proj2 +> | > +> | using lexicographical-compare-three-way-result-t = +> | invoke_result_t< +> | Comp, +> | typename projected::value_type, +> | typename projected::value_type +> | >; // exposition-only +> | +> | constexpr bool is-lexicographical-compare-three-way-result-ordering = +> | same-as-one-of< +> | lexicographical-compare-three-way-result-t< +> | I1, I2, Comp, Proj1, Proj2 +> | >, +> | strong_ordering, weak_ordering, partial_ordering>; //exposition-only +> | +> | template< +> | input_iterator I1, sentinel_for S1, +> | input_iterator I2, sentinel_for S2, +> | class Comp = compare_three_way, +> | class Proj1 = identity, +> | class Proj2 = identity +> | > +> | requires +> | is-lexicographical-compare-three-way-result-ordering< +> | I1, I2, Comp, Proj1, Proj2 +> | > +> | constexpr auto +> | ranges::lexicographical_compare_three_way( +> | I1 first1, +> | S1 last1, +> | I2 first2, +> | S2 last2, +> | Comp comp = {}, +> | Proj1 proj1 = {}, +> | Proj2 proj2 = {} +> | ) -> common_comparison_category_t< +> | decltype( +> | comp(proj1(\*first1), proj2(\*first2)) +> | ), +> | strong_ordering +> | >; +> | +> | template< +> | ranges::input_range R1, +> | ranges::input_range R2, +> | class Comp = compare_three_way, +> | class Proj1 = identity, +> | class Proj2 = identity +> | > +> | requires +> | is-lexicographical-compare-three-way-result-ordering< +> | iterator_t\, iterator_t\, Comp, Proj1, Proj2 +> | > +> | constexpr auto +> | ranges::lexicographical_compare_three_way( +> | R1&& r1, +> | R2&& r2, +> | Comp comp = {}, +> | Proj1 proj1 = {}, +> | Proj2 proj2 = {} +> | ) -> common_comparison_category_t< +> | decltype( +> | comp(proj1(*ranges::begin(r1)), proj2(*ranges::begin(r2))) +> | ), +> | strong_ordering +> | >; +> ::: + +## Add to §27.8.12 [alg.three.way] + +> | template +> | constexpr auto +> | lexicographical_compare_three_way(InputIterator1 b1, InputIterator1 e1, +> | InputIterator2 b2, InputIterator2 e2); + +> ::: add +> | template +> | concept same-as-one-of = (same_as or ...); // exposition only +> | +> | template< +> | input_iterator I1, +> | input_iterator I2, +> | class Comp, +> | class Proj1, +> | class Proj2 +> | > +> | using lexicographical-compare-three-way-result-t = +> | invoke_result_t< +> | Comp, +> | typename projected::value_type, +> | typename projected::value_type +> | >; // exposition-only +> | +> | constexpr bool is-lexicographical-compare-three-way-result-ordering = +> | same-as-one-of< +> | lexicographical-compare-three-way-result-t< +> | I1, I2, Comp, Proj1, Proj2 +> | >, +> | strong_ordering, weak_ordering, partial_ordering>; //exposition-only +> | +> | template< +> | input_iterator I1, sentinel_for S1, +> | input_iterator I2, sentinel_for S2, +> | class Comp = compare_three_way, +> | class Proj1 = identity, +> | class Proj2 = identity +> | > +> | requires +> | is-lexicographical-compare-three-way-result-ordering< +> | I1, I2, Comp, Proj1, Proj2 +> | > +> | constexpr auto +> | ranges::lexicographical_compare_three_way( +> | I1 first1, +> | S1 last1, +> | I2 first2, +> | S2 last2, +> | Comp comp = {}, +> | Proj1 proj1 = {}, +> | Proj2 proj2 = {} +> | ) -> common_comparison_category_t< +> | decltype( +> | comp(proj1(\*first1), proj2(\*first2)) +> | ), +> | strong_ordering +> | >; +> | +> | template< +> | ranges::input_range R1, +> | ranges::input_range R2, +> | class Comp = compare_three_way, +> | class Proj1 = identity, +> | class Proj2 = identity +> | > +> | requires +> | is-lexicographical-compare-three-way-result-ordering< +> | iterator_t\, iterator_t\, Comp, Proj1, Proj2 +> | > +> | constexpr auto +> | ranges::lexicographical_compare_three_way( +> | R1&& r1, +> | R2&& r2, +> | Comp comp = {}, +> | Proj1 proj1 = {}, +> | Proj2 proj2 = {} +> | ) -> common_comparison_category_t< +> | decltype( +> | comp(proj1(\*ranges::begin(r1)), proj2(\*ranges::begin(r2))) +> | ), +> | strong_ordering +> | >; +> ::: + +- [1]{.pnum} Let N be the minimum integer between distance(first1,s1) and distance(first2,s2). Let E(n) be comp(proj1(*(first1 + n)), proj2(*(first2 + n))). +- [2]{.pnum} Returns: E(i), where i is the smallest integer in [0, N) such that E(i) != 0 is true, or (distance(first1,s1) <=> distance(first2, s2) if no such integer exists. +- [3]{.pnum} Complexity: At most N applications of comp, proj1, proj2. + +--- +references: + - id: GitHub + citation-label: GitHub + title: "implementation" + author: + - family: Regev + given: Ran + URL: https://github.com/regevran/IlPapersFork/tree/P2022/master + + - id: Tests + citation-label: Tests + title: "tests" + author: + - family: Regev + - given: Ran + URL: https://github.com/regevran/IlPapersFork/tree/P2022/master/P2022/tests +--- + + +# Acknowledgements + Alex Dathskovsky + Avi Korzac + Lee-or Saar + Mor Elmaliach + Yaron Meister diff --git a/P2022/generated/P2022R0.pdf b/P2022/generated/P2022R0.pdf new file mode 100644 index 0000000..bdf04d8 Binary files /dev/null and b/P2022/generated/P2022R0.pdf differ diff --git a/P2022/generated/P2022R1.pdf b/P2022/generated/P2022R1.pdf new file mode 100644 index 0000000..0447551 Binary files /dev/null and b/P2022/generated/P2022R1.pdf differ diff --git a/P2022/tests/CMakeLists.txt b/P2022/tests/CMakeLists.txt new file mode 100644 index 0000000..7e43f50 --- /dev/null +++ b/P2022/tests/CMakeLists.txt @@ -0,0 +1,14 @@ + +cmake_minimum_required(VERSION 3.16) + +set(CMAKE_C_COMPILER gcc-11) +set(CMAKE_CXX_COMPILER g++-11) + +project(P2022) + +include_directories( + header +) + +add_subdirectory(units) + diff --git a/P2022/tests/header/3way.hpp b/P2022/tests/header/3way.hpp new file mode 100644 index 0000000..55afe1a --- /dev/null +++ b/P2022/tests/header/3way.hpp @@ -0,0 +1,128 @@ + + +#include +#include + + +namespace std +{ + template < + typename T, + typename... U + > + concept same_as_any_of = (std::same_as or ...); // exposition only +} + +namespace std::ranges +{ + template< + input_iterator I1, + input_iterator I2, + class Comp, + class Proj1, + class Proj2 + > + using lexicographical_compare_three_way_result_t = + invoke_result_t< + Comp, + typename projected::value_type, + typename projected::value_type + >; // exposition-only + + template< + std::input_iterator I1, + std::input_iterator I2, + class Comp, + class Proj1, + class Proj2 + > + constexpr bool is_lexicographical_compare_three_way_result_ordering = + std::same_as_any_of< + lexicographical_compare_three_way_result_t< + I1, I2, Comp, Proj1, Proj2 + >, + std::strong_ordering, std::weak_ordering, std::partial_ordering>; //exposition-only + + template< + input_iterator I1, sentinel_for S1, + input_iterator I2, sentinel_for S2, + class Comp = compare_three_way, + class Proj1 = identity, + class Proj2 = identity + > + requires + is_lexicographical_compare_three_way_result_ordering< + I1, I2, Comp, Proj1, Proj2 + > + constexpr auto + lexicographical_compare_three_way( + I1 first1, + S1 last1, + I2 first2, + S2 last2, + Comp comp = {}, + Proj1 proj1 = {}, + Proj2 proj2 = {} + ) -> common_comparison_category_t< + decltype( + comp(proj1(*first1), proj2(*first2)) + ), + strong_ordering + > + { + while (first1 != last1) + { + if (first2 == last2) + { + return strong_ordering::greater; + } + + if (auto cmp = comp(proj1(*first1), proj2(*first2)); + cmp != 0 ) + { + return cmp; + } + + ++first1; + ++first2; + } + + // GCC 11 implementation with the + // note: See PR 94006 + return (first2 == last2) <=> true; + } + + template< + ranges::input_range R1, + ranges::input_range R2, + class Comp = compare_three_way, + class Proj1 = identity, + class Proj2 = identity + > + requires + is_lexicographical_compare_three_way_result_ordering< + iterator_t, iterator_t, Comp, Proj1, Proj2 + > + constexpr auto + lexicographical_compare_three_way( + R1&& r1, + R2&& r2, + Comp comp = {}, + Proj1 proj1 = {}, + Proj2 proj2 = {} + ) -> common_comparison_category_t< + decltype( + comp(proj1(*ranges::begin(r1)), proj2(*ranges::begin(r2))) + ), + strong_ordering + > + { + return lexicographical_compare_three_way( + ranges::begin(r1), ranges::end(r1), + ranges::begin(r2), ranges::end(r2), + move(comp), + move(proj1), + move(proj2)); + } +} + diff --git a/P2022/tests/units/CMakeLists.txt b/P2022/tests/units/CMakeLists.txt new file mode 100644 index 0000000..ea3546e --- /dev/null +++ b/P2022/tests/units/CMakeLists.txt @@ -0,0 +1,43 @@ + +cmake_minimum_required(VERSION 3.16) + +find_package(Catch2 3 REQUIRED) + +project( + P2022Tests + LANGUAGES CXX +) + +set(CMAKE_BUILD_TYPE Debug) + +add_compile_options( + -fconcepts-diagnostics-depth=5 +) + +# the tests +add_executable( + ${PROJECT_NAME} + nop.cpp + containers.cpp + basic_check.cpp + unordered.cpp + t1.cpp + avi_tests.cpp + ranges.cpp + compilation_error.cpp +) + +set_target_properties( + ${PROJECT_NAME} + PROPERTIES + CXX_STANDARD 20 + CXX_STANDARD_REQUIRED YES + CXX_EXTENSIONS NO +) + + +target_link_libraries( + ${PROJECT_NAME} + PRIVATE Catch2::Catch2WithMain +) + diff --git a/P2022/tests/units/avi_tests.cpp b/P2022/tests/units/avi_tests.cpp new file mode 100644 index 0000000..427f2a8 --- /dev/null +++ b/P2022/tests/units/avi_tests.cpp @@ -0,0 +1,185 @@ +#include "catch2/catch_all.hpp" + +#include "3way.hpp" + +#include + +TEST_CASE("test with default projections and compare function") +{ + // generating two lists, l1 and l2, where until the kth index they are identical and after it + // each element in l2 is greater than l1 by one + + int n = 10; + int k = static_cast(0.75 * n); + + std::vector l1{}; + l1.reserve(n); + std::vector l2{}; + l2.reserve(n); + + std::random_device rd{}; + std::mt19937 gen{ rd() }; + std::uniform_int_distribution distrib(std::numeric_limits::min(), std::numeric_limits::max()); + + for (int i = 0; i < n; ++i) + { + int l1Elem = distrib(gen); + int l2Elem = i < k ? l1Elem : l1Elem + 1; + l1.push_back(l1Elem); + l2.push_back(l2Elem); + } + + auto res = + std::ranges::lexicographical_compare_three_way( + std::begin(l1), std::end(l1), + std::begin(l2), std::end(l2) + ); + + CHECK(res == std::strong_ordering::less); +} + +TEST_CASE("test with custom compare function") +{ + // generating two lists, l1 in small caps and l2 is big caps, + // which have the same words but in different order + // using a comp function which is case INSENSETIVE + + std::vector lowerCaseNums{ "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten" }; + std::vector upperCaseNums{ "ONE", "FOUR" , "THREE", "TWO", "NINE", "EIGHT", "SEVEN", "SIX", "FIVE", "TEN" }; + + auto caseInsensitiveCmp = [](std::string x, std::string y) -> std::strong_ordering + { + for (char& c : x) + { + c = std::toupper(c); + } + for (char& c : y) + { + c = std::toupper(c); + } + + if (x < y) + { + return std::strong_ordering::less; + } + else if (x > y) + { + return std::strong_ordering::greater; + } + else + { + return std::strong_ordering::equal; + } + }; + + auto res = + std::ranges::lexicographical_compare_three_way( + std::begin(lowerCaseNums), std::end(lowerCaseNums), + std::begin(upperCaseNums), std::end(upperCaseNums), + caseInsensitiveCmp + ); + + CHECK(res == std::strong_ordering::greater); +} + +TEST_CASE("test with custom compare function which returns std::partial_ordering::unordered") +{ + // generating two lists, l1 and l2, where until the kth index they are identical and after it + // each element in l2 an empty std::optional + + int n = 10; + int k = static_cast(0.75 * n); + + std::vector> l1{}; + l1.reserve(n); + std::vector> l2{}; + l2.reserve(n); + + std::random_device rd{}; + std::mt19937 gen{ rd() }; + std::uniform_int_distribution<> distrib(std::numeric_limits::min(), std::numeric_limits::max()); + + for (int i = 0; i < n; ++i) + { + std::optional l1Elem = distrib(gen); + std::optional l2Elem = i < k ? l1Elem : std::optional{}; + l1.push_back(l1Elem); + l2.push_back(l2Elem); + } + + auto myCmp = [](const std::optional& x, const std::optional& y) -> std::partial_ordering + { + if (x && y) + { + std::strong_ordering so{ x <=> y }; + if (so < 0) + { + return std::partial_ordering::less; + } + else if (so > 0) + { + return std::partial_ordering::greater; + } + else + { + return std::partial_ordering::equivalent; + } + } + else + { + return std::partial_ordering::unordered; + } + }; + + auto res = + std::ranges::lexicographical_compare_three_way( + std::begin(l1), std::end(l1), + std::begin(l2), std::end(l2), + myCmp + ); + + CHECK(res == std::partial_ordering::unordered); +} + +TEST_CASE("test with custom projections and custom compare function") +{ + // generating two lists, l1 and l2, where the elements of l2 are twice as big + // as the elements in l1 + // with two different projects + // l1's projection will multiply its elements by 6 and add one + // l2's projection will multiply its element by 3 and subtract one + // the comp function will subtract one from l1 and + // add one to l2, and then 3-way compare them + + constexpr std::size_t n{ 10U }; + + std::array l1{}; + std::array l2{}; + + std::random_device rd{}; + std::mt19937 gen{ rd() }; + std::uniform_int_distribution distrib(std::numeric_limits::min(), std::numeric_limits::max()); + + for (int i = 0; i < n; ++i) + { + int elem = distrib(gen); + l1[i] = elem; + l2[i] = 2 * elem; + } + + auto l1Proj = [](int l1Elem) { return 6 * l1Elem + 1; }; + auto l2Proj = [](int l2Elem) { return 3 * l2Elem - 1; }; + + auto cmp = [](int l1Elem, int l2Elem) { return --l1Elem <=> ++l2Elem; }; + + auto res = + std::ranges::lexicographical_compare_three_way( + std::begin(l1), std::end(l1), + std::begin(l2), std::end(l2), + cmp, + l1Proj, + l2Proj + ); + + CHECK(res == std::strong_ordering::equal); +} \ No newline at end of file diff --git a/P2022/tests/units/basic_check.cpp b/P2022/tests/units/basic_check.cpp new file mode 100644 index 0000000..f7f2b51 --- /dev/null +++ b/P2022/tests/units/basic_check.cpp @@ -0,0 +1,94 @@ + + +#include "catch2/catch_all.hpp" + +using namespace std; + +template< + input_iterator F1, + input_iterator L1, + input_iterator F2, + input_iterator L2, + class Comp = compare_three_way, + class Proj1 = identity, + class Proj2 = identity +> +requires + same_as, invoke_result_t>, strong_ordering> || + same_as, invoke_result_t>, weak_ordering> || + same_as, invoke_result_t>, partial_ordering> +auto compare( + F1 f1, L1 l1, + F2 f2, L2 l2, + Comp comp = {}, + Proj1 p1 = {}, + Proj2 p2 = {} + ) -> + common_comparison_category_t< + decltype( + invoke(comp, invoke(p1,*f1), invoke(p2,*f2))), strong_ordering> +{ + while (f1 != l1) + { + if (f2 == l2) + { + return strong_ordering::greater; + } + + if ( + auto cmp = comp(invoke(p1, *f1), invoke(p2, *f2)); + cmp != 0 + ) + { + return cmp; + } + + ++f1; + ++f2; + } + + // GCC 11 implementation with the + // note: See PR 94006 + return (f2 == l2) <=> true; +} + +struct goo +{ + template + auto operator()(T t, U u) -> partial_ordering + { + + static_assert(std::same_as); + static_assert(std::same_as); + + int char_as_int = static_cast(u); + if (char_as_int < 10) + { + return char_as_int <=> t; + } + else + { + return partial_ordering::unordered; + } + } + + /* + auto operator()(int t, char u) -> partial_ordering + { + return partial_ordering::less; + } + */ +}; + + +TEST_CASE("basic_check") +{ + vector v1{1,2,3,4}; + vector v2{'a', 'b'}; + + compare( + v1.begin(), v1.end(), + v2.begin(), v2.end(), + goo{} + ); +} diff --git a/P2022/tests/units/compilation_error.cpp b/P2022/tests/units/compilation_error.cpp new file mode 100644 index 0000000..fd0179a --- /dev/null +++ b/P2022/tests/units/compilation_error.cpp @@ -0,0 +1,30 @@ + +#include "3way.hpp" +#include "catch2/catch_all.hpp" + + +struct BadComp +{ + template + auto operator()(T t, U u) -> bool + { + return 5 > 6; + } +}; + +TEST_CASE("compilation error") +{ + std::vector v1{0, 1, 2, 3}; + std::vector v2{0, 1, 2, 3}; + + // open the followinf section to make sure + // Comp doesn't compile correctly + /* + auto res = + std::ranges::lexicographical_compare_three_way( + std::ranges::begin(v1), std::ranges::end(v1), + std::ranges::begin(v2), std::ranges::end(v2), + BadComp{} + ); + */ +} diff --git a/P2022/tests/units/containers.cpp b/P2022/tests/units/containers.cpp new file mode 100644 index 0000000..524f09c --- /dev/null +++ b/P2022/tests/units/containers.cpp @@ -0,0 +1,21 @@ + + +#include +#include "catch2/catch_all.hpp" + +TEST_CASE("containers") +{ + std::vector v1{0, 1, 2, 3}; + std::vector v2{0, 1, 2, 4}; + + auto res = + std::lexicographical_compare_three_way( + std::begin(v1), std::end(v1), + std::begin(v2), std::end(v2), + std::compare_three_way{} + ); + + CHECK(res == std::strong_ordering::less); +} + + diff --git a/P2022/tests/units/nop.cpp b/P2022/tests/units/nop.cpp new file mode 100644 index 0000000..88c7a05 --- /dev/null +++ b/P2022/tests/units/nop.cpp @@ -0,0 +1,10 @@ + + +#include "3way.hpp" +#include "catch2/catch_all.hpp" + +TEST_CASE("nop") +{ +} + + diff --git a/P2022/tests/units/ranges.cpp b/P2022/tests/units/ranges.cpp new file mode 100644 index 0000000..e747cbe --- /dev/null +++ b/P2022/tests/units/ranges.cpp @@ -0,0 +1,15 @@ + +#include "3way.hpp" +#include "catch2/catch_all.hpp" + +TEST_CASE("ranges") +{ + std::vector v1{5, 6, 7, 8}; + std::vector v2{0, 1, 2, 3}; + + auto res = + std::ranges::lexicographical_compare_three_way(v1, v2); + + CHECK(res == std::strong_ordering::greater); +} + diff --git a/P2022/tests/units/t1.cpp b/P2022/tests/units/t1.cpp new file mode 100644 index 0000000..77da8d3 --- /dev/null +++ b/P2022/tests/units/t1.cpp @@ -0,0 +1,19 @@ + + +#include "3way.hpp" +#include "catch2/catch_all.hpp" + +TEST_CASE("t1") +{ + std::vector v1{0, 1, 2, 3}; + std::vector v2{0, 1, 2, 4}; + + auto res = + std::ranges::lexicographical_compare_three_way( + std::ranges::begin(v1), std::ranges::end(v1), + std::ranges::begin(v2), std::ranges::end(v2) + ); + + CHECK(res == std::strong_ordering::less); +} + diff --git a/P2022/tests/units/unordered.cpp b/P2022/tests/units/unordered.cpp new file mode 100644 index 0000000..c6ddad8 --- /dev/null +++ b/P2022/tests/units/unordered.cpp @@ -0,0 +1,40 @@ + + +#include "3way.hpp" +#include "catch2/catch_all.hpp" + +struct CharIntComp +{ + template + auto operator()(T t, U u) -> std::partial_ordering + { + static_assert(std::same_as); + static_assert(std::same_as); + + int char_as_int = static_cast(u); + if (char_as_int < 10) + { + return char_as_int <=> t; + } + else + { + return std::partial_ordering::unordered; + } + } +}; + +TEST_CASE("unordered") +{ + std::vector v1{0, 1, 2, 3}; + std::vector v2{'a', 'b'}; + + auto res = + std::ranges::lexicographical_compare_three_way( + std::ranges::begin(v1), std::ranges::end(v1), + std::ranges::begin(v2), std::ranges::end(v2), + CharIntComp{} + ); + + CHECK(res == std::partial_ordering::unordered); +} + diff --git a/P2022/ulem.sty b/P2022/ulem.sty new file mode 100644 index 0000000..85ebb06 --- /dev/null +++ b/P2022/ulem.sty @@ -0,0 +1,376 @@ +% +% U L E M . S T Y [2019-11-18] +% +% The ulem package provides various types of underlining that can stretch +% between words and be broken across lines in LaTeX or plain TeX. +% In LaTeX ulem replaces italics with underlining in \em-phasized text. +% It is most suitable for simple text such as {\em ibid.} or \emph{\LaTeX: +% A Document Preparation System} that may need to be underlined in a +% manuscript submitted for publication. A declaration of \normalem (or +% the \usepackage option "normalem") restores the normal \em behavior. +% +% Full instructions appear in ulem.ltx (ulem.pdf). In summary: +% +% \uline{important} underlined text +% \uuline{urgent} double-underlined text +% \uwave{boat} wavy underline +% \sout{wrong} line drawn through word +% \xout{removed} marked over with //////. +% \dashuline{dashing} dash underline +% \dotuline{dotty} dotted underline +% +% {\em phasized\/} | In LaTeX, by default, these are underlined; use +% \emph{asized} | \normalem or [normalem] to restore italics +% \useunder{\uwave}{\bf}{\textbf} +% use wavy underline in place of bold face +% Use \markoverwith for defining new types of underlining. +% +% Copyright (c) 1989-2011 by Donald Arseneau (Vancouver, Canada; asnd@triumf.ca) +% +% This software may be freely transmitted, reproduced, or modified for any +% purpose provided that this copyright notice is left intact. +% (Small excerpts may be taken and used without any restriction.) +% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% Defend against multiple loading. +\expandafter \ifx \csname UL@box\endcsname \relax \else + \immediate\write16{ulem.sty refuses to load twice. }\endinput \fi + +% Set catcode of @ in case it isn't a "letter" already +\chardef\ULthickness\catcode\string`\@ % hold catcode temporarily +\catcode\string`\@=11 + +% \UL@protected = \protected, if available, else \relax + +\begingroup +\global\expandafter\let\expandafter\UL@protected\csname protected\endcsname +\endgroup + +\UL@protected\def\uline{\relax \ifmmode\expandafter\underline + \else \bgroup\expandafter\ULset\fi} + +\newbox\UL@box +\newbox\UL@hyphenbox +\newskip\UL@skip +\newtoks\UL@hook +\newdimen\UL@height \UL@height=\maxdimen % flags being unused +\newcount\UL@pe + +\UL@protected\def\UL@end *{\relax\relax}% something harmless but unique + +% For regular underlines, set the depth based on the font, or retain +% the preset value, then start underlining. +\def\ULset{\UL@setULdepth + \def\UL@leadtype{\leaders \hrule \@height\UL@height \@depth\ULdepth}% + \ifmmode \ULdepth-4\p@ \fi + \UL@height-\ULdepth \advance\UL@height\ULthickness \ULon} + +% Automatically set \ULdepth if it is to be automatic (flagged by \maxdimen) +\def\UL@setULdepth{\relax + \ifdim\ULdepth=\maxdimen % Set depth based on font, if not set already + \setbox\UL@box\hbox{{(j}}\ULdepth\dp\UL@box\advance\ULdepth.4\p@ + % use setbox to support plain TeX + \fi} + +% \ULon simply calls \UL@on (possibly \UL@on=\UL@onin) for text mode, but +% \UL@onmath if it is math mode. +\def\ULon{\ifmmode \expandafter\UL@onmath\else \expandafter\UL@on\fi} + +% \UL@on sets the engine of underline running, and tells it +% where to stop. #1 = the relevant text. +\long\def\UL@on#1{\leavevmode\UL@ender \let\UL@on\UL@onin + \everymath{\UL@hrest}\everyvbox{\UL@hrest}\let\hskip\UL@hskip + \let\\\UL@cr \let\-\UL@dischyp \let\newline\UL@newline \let\ \UL@space + \def\hfil{\hskip\z@ plus1fil\relax}\def\hfill{\hskip\z@ plus1fill\relax}% + \def\hss{\hskip\z@ plus1filminus1fil\relax}\let\penalty\UL@penalty + \the\UL@hook + \UL@word\@empty#1\xdef\UL@spfactor{\the\spacefactor} \UL@end * } + +% This is what \ULon does when it appears nested in an inner place. +\long\def\UL@onin#1{\leavevmode\UL@ender % when nested, do multiple underlining + \ifdim\ULdepth=\maxdimen\else + \UL@height\ULthickness \advance\ULdepth\thr@@\UL@height \advance\UL@height-\ULdepth + \fi + \setbox\UL@box\hbox{{#1}}% + \let\UL@start\relax\UL@putbox\egroup} +% \UL@putbox is disabled in inner mode, so re-enable it by changing \UL@start +% \UL@hrest is implicit due to \everyhbox. Double braces for \hbox are in +% lieu of \color@begin(end)group. + +% This is what \ULon does in math mode. +\def\UL@onmath#1{\UL@ender\mathord{\UL@hrest\mathop{\kern\z@#1}\limits\sb + {\UL@leadtype\LA@hskip\p@ plus1fill}}\egroup} + +\def\UL@unegroup{} +\gdef\UL@ender{} +% end-brace matching hack for when command is used as a font declaration: +\def\UL@swender{\ifnum`{=\z@\fi\aftergroup}\gdef\UL@ender{}} + +% must expand to nothing outside the ifs for syntactical spaces to work. +% the \expandafters get rid of the \@empty inserted at the beg. of word +\long\def\UL@word#1 {\expandafter\UL@start#1 % + \expandafter\ifx\expandafter\UL@end#1\egroup\egroup + \unskip \unskip \unskip % remove extra leader at end + \spacefactor\UL@spfactor \let\UL@word\egroup + \else % not finished + \ifmmode\else \ifdim\lastskip=\z@\else % allow syntactical spaces + \global\UL@skip\lastskip \unskip + \UL@stop \UL@leaders + \fi\fi + \fi \UL@word\@empty}% \@empty preserves braces in param + +% \UL@start: start of each chunk. It gives two levels of grouping. +% Each chunk is ended by \UL@stop. Local intermissions go like +% \UL@stop...\UL@start. +\def\UL@start{\setbox\UL@box\hbox\bgroup\everyhbox{\UL@hrest}% +% the following are to cope with stops (\ ,\- etc) within extra braces + \let\UL@start\@empty \def\UL@unegroup{\bgroup\bgroup}\let\UL@leadtype\@empty + \bgroup \kern-3sp\kern3sp % kerns so I can test for beginning of list + \if@ignore \global\@ignorefalse \ignorespaces \fi} + +\def\UL@stop{\global\UL@pe\lastpenalty \unpenalty % penalty in \UL@pe + \ifnum\lastkern=\thr@@ \egroup\egroup % Nothing in hbox...but make sure: + \ifdim\wd\UL@box=\z@ \else \UL@putbox \fi % something in box so print it + \else \egroup\egroup \UL@putbox % something in box so print it + \fi \ifnum\UL@pe=\z@ \else \LA@penalty\UL@pe \fi % use penalty from inside box + \UL@unegroup} +% notice that a box with only a penalty in it is discarded, but the penalty +% is still used! This is so a series of discardable glues and penalties +% behaves properly. + +\def\UL@putbox{\ifx\UL@start\@empty \else % not inner + \vrule\@width\z@ \LA@penalty\@M + {\UL@skip\wd\UL@box \UL@leaders \kern-\UL@skip}% + \box\UL@box + \fi} + +% With interword leaders, give some overlap to avoid gaps caused by +% round-off errors in the printing program. Needs \unskip \unskip \unskip +% above. This version overlaps 1/300 inch, which looks good at high +% resolution, and will still work down to ~150 dpi. Change the value +% of \UL@pixel if necessary. + +\newdimen\UL@pixel \UL@pixel=1in \divide\UL@pixel 300 + +\def\UL@leaders{{\LA@hskip-\UL@pixel \advance\UL@skip\tw@\UL@pixel + \UL@leadtype\LA@hskip\UL@skip \LA@hskip-\UL@pixel}} + +% restore some things for inside math or \mbox +\def\UL@hrest{\let\ \LA@space \let\-\@empty \let\penalty\LA@penalty} + +\let\LA@space\ % +\UL@protected\def\UL@space{\LA@space \global\UL@skip\lastskip \unskip \UL@reskip}% + +% Hyphenation is done by explicit \discretionary. The overlapping melds +% with the running overlap because it *is* part of the running overlap: +% The word fragment is extended by the width of the hyphenation which is +% then overlapped by leaders. The discretionary may occupy this space +% if a break occurs; otherwise the next syllable gets doubly-overlapped +% (in registration) for a distance of the hyphen's width. +\UL@protected\def\UL@dischyp{\global\setbox\UL@hyphenbox\hbox + {\ifnum \hyphenchar\font<\z@ \string-\else \char\hyphenchar\font \fi}% + \kern\wd\UL@hyphenbox \LA@penalty\@M + \UL@stop \kern-\wd\UL@hyphenbox + \discretionary{\box\UL@hyphenbox}{}{}\UL@start} + +\let\LA@penalty\penalty +\UL@protected\def\UL@penalty{\relax\ifhmode \afterassignment\UL@@penalty\count@ + \else\LA@penalty\fi} +\def\UL@@penalty{\LA@penalty \ifnum\count@=\z@ + \@ne \else \count@ \fi % zero penalty => no penalty, so use 1 instead. + \UL@stop \UL@start} + +% The test \ifx\ \LA@space \else means we are neither in math mode nor an +% \mbox, so it is safe to stop the current \UL@box. \ , \- , and \penalty +% (= \linebreak or \nolinebreak) are common enough that they are restored +% directly (by \UL@hrest); \\, \newline, \hskip (= \hspace) are rare enough +% that the test is incorporated in their UL versions. This adds processing +% when they're used, but saves processing in \UL@hrest called by \everymath +% \everyvbox and \everyhbox. + +\let\LA@hskip\hskip +\UL@protected\def\UL@hskip{\ifx\ \LA@space \LA@hskip \else + \afterassignment\UL@reskip \global\UL@skip \fi} + +\def\UL@reskip{\UL@stop \UL@leaders \UL@start} + +% Redefine \\ and \newline so the vertical space from \\[ ] is not lost +% and so the \hfil is not underlined! \\ and \newline do nothing if inside +% inner braces. + +\UL@protected\def\UL@cr{\unskip \ifx\ \LA@space \let\UL@vad\@gobble + \else \UL@stop \unskip\unskip\unskip \let\UL@vad\vadjust \fi + \@ifstar{\UL@vad{\LA@penalty\@M}\UL@cra}\UL@cra} +\def\UL@cra{\@ifnextchar[\UL@crb\UL@newline} +\def\UL@crb[#1]{\UL@vad{\vskip#1}\UL@newline} + +\UL@protected\def\UL@newline{\ifx\UL@start\@empty % (\UL@cr may have \UL@stop-ed already) + \unskip \ifx\ \LA@space \else \UL@stop \unskip\unskip\unskip \fi\fi + \LA@hskip \z@\@plus.0001fil\LA@penalty -\@M \UL@start} + +% That concludes the basic underlining. To put various other objects +% (characters) under (or over) text we need to define \markoverwith +% to set the overlay material in a box, and use leaders of that box for +% overlaying the text. Here, the meaning of \UL@pixel is changed so +% that `pixel' size = box size. Note that we generally need \leaders +% (not \cleaders) for text, because an underline will be a patchwork +% of small \leaders, and the characters must stay in registration. +% However, we "hook" the leaders command so specific applications can +% reassign it (\let\ULleaders\xleaders or \let\ULleaders\cleaders). +% +\newbox\ULC@box +\let\ULleaders\leaders + +\UL@protected\def\markoverwith#1{\leavevmode + \setbox\ULC@box\hbox{{#1}}\UL@pixel.5\wd\ULC@box + \ifmmode \setbox\ULC@box\hbox{\raise1.4ex\box\ULC@box}% + \dp\ULC@box-1.4ex\ht\ULC@box\z@ \def\UL@leadtype{\cleaders\copy\ULC@box}% + \else + \def\UL@leadtype{\ULleaders\copy\ULC@box}% + \fi} + +% Now define various special underlines. All the definitions go like +% \def \command {\bgroup \markoverwith{something} \ULon} + +% For drawing a wavey underline instead of a straight one the command +% is \uwave (under-wave) which uses the wiggle from 6-pt lasy font: + +\UL@protected\def\uwave{\leavevmode \bgroup + \ifdim \ULdepth=\maxdimen \ULdepth 3.5\p@ + \else \advance\ULdepth2\p@ + \fi \markoverwith{\lower\ULdepth\hbox{\sixly \char58}}\ULon} +\font\sixly=lasy6 % does not re-load if already loaded, so no memory drain. + +% To draw a double underline under text, use \uuline{text} + +\UL@protected\def\uuline{\leavevmode \bgroup + \UL@setULdepth + \ifx\UL@on\UL@onin \advance\ULdepth2.8\p@\fi + \markoverwith{\lower\ULdepth\hbox + {\kern-.03em\vbox{\hrule width.2em\kern1\p@\hrule}\kern-.03em}}% + \ULon} + +% To draw a line through text instead of under it (strike out) do +% `under'-line with negative depth. Note that this one uses a real +% line, not characters, so there is no \markoverwith. + +\UL@protected\def\sout{\leavevmode \bgroup \ULdepth=-.55ex \ULset} + +% To mark //// over text instead of underlining (x-out) +% +\UL@protected\def\xout{\leavevmode \bgroup + \markoverwith{\hbox to.35em{\hss/\hss}}\ULon} + +\UL@protected\def\dotuline{\leavevmode \bgroup + \UL@setULdepth + \ifx\UL@on\UL@onin \advance\ULdepth2\p@\fi + \markoverwith{\begingroup + %\advance\ULdepth0.08ex + \lower\ULdepth\hbox{\kern.06em .\kern.04em}% + \endgroup}% + \ULon} + +\UL@protected\def\dashuline{\leavevmode \bgroup + \UL@setULdepth + \ifx\UL@on\UL@onin \advance\ULdepth2\p@\fi + \markoverwith{\kern.13em + \vtop{\kern\ULdepth \hrule width .3em}% + \kern.13em}\ULon} + +% A command to declare that an underline command should be used in +% place of a particular font selection: +% \useunder {underline_command}{font_declaration}{font_command} +% e.g.: \useunder{\uuline}{\bfseries}{\textbf} +% \useunder{\uwave}{\bf}{} + +\UL@protected\def\useunder#1#2#3{\relax + \ifx\relax#2\relax\else % declaration command given + \UL@protected\def#2{\def\@tempa{#1}\global\let\UL@ender\UL@swender + \expandafter\@tempa\expandafter{\ifnum\z@=\string`}\fi}% + \fi + \ifx\relax#3\relax\else % argumentative command + \UL@protected\def#3{#1}% + \fi} + +\expandafter\ifx \csname @ifundefined\endcsname \relax + +% Allow plain TeX to use ulem.sty: + \def\@height{height} + \def\@depth{depth} + \def\@width{width} + \def\@empty{} + \long\def\@gobble#1{} + \long\def\@firstoftwo#1#2{#1}% + \long\def\@secondoftwo#1#2{#2}% +% Do non-outer \newif with no visible \if's or \fi's when skipping + \csname newif\expandafter\endcsname \csname if@ignore\endcsname + +\else + + \let\LA@em\em \let\LA@emph\emph + \expandafter\let\expandafter\LA@Pem \csname em \endcsname + \expandafter\let\expandafter\LA@Pemph \csname emph \endcsname + \def\ULforem{\useunder{\uline}{\em}{\emph}} + \def\normalem{\let\em\LA@em \let\emph\LA@emph + \expandafter\let\csname em \endcsname\LA@Pem + \expandafter\let\csname emph \endcsname\LA@Pemph} + \ULforem % default is to use underlining for \em, + +\fi + +% Process LaTeX \package options; plain TeX skips this section + +\expandafter\ifx\csname ProvidesPackage\endcsname \relax \else + \ProvidesPackage{ulem}[2019/11/18] + \DeclareOption{normalem}{\normalem} + \DeclareOption{ULforem}{\ULforem} + \DeclareOption{normalbf}{} + \DeclareOption{UWforbf}{\useunder{\uwave}{\bf}{\textbf}} + \ProcessOptions +% + \newcommand\UL@marpar[2][\ULmp@opt@arg]{\gdef\ULmp@opt@arg{#2}% + \ifx\ \LA@space \@latexerr{Marginpar lost}% + \else \UL@stop \LA@marginpar[#1]{#2}\UL@start \fi} +% + \AtBeginDocument{\let\LA@marginpar\marginpar}% +% + \addto@hook\UL@hook{\let\marginpar\UL@marpar} +\fi + +\catcode`@=\ULthickness % Scratch meaning: restore catcode of @ + +\def\ULthickness{.4pt}% can change this with \renewcommand +\newdimen\ULdepth \ULdepth=\maxdimen +% "maxdimen" depth causes the depth to be set according to the font. You +% can change \ULdepth for a permanent setting or a special effect (\sout). + +\endinput + + +% Previous bug-finders: Esther Hu (\hfill in plain); Lones Smith (\tt\-); +% Steve Anderson (\ooalign accents); Thanassi Protopapas ( { in tables). +% The bug finders' fee is now $0.00; it will double for each new bug found. +% Version (identified by year) +% 1994: +% Many changes! Notably: LaTeX2e options and \emph. Nesting works (somewhat). +% Behavior with inner braces is more consistent (not stripped). \useunder. +% Better underwave (using lasy6). Special underlines are not commented out. +% patch 1995: fix \UL@swender to work in {tabular}; make hyphenation join +% well; crude math support; eliminate \@clb +% 1996: use "\csname ProvidesPackage\endcsname", tidying. +% 1997: fix \\ when LaTeX changed; remove extra overlap in putbox. +% 2000: hook (and marginpar) +% 2004: Fix spacing in \uwave and \xout. \ULleaders hook. +% 2009: Accept \par in argument (\long) +% 2010: Include \dotuline and \dashuline, typeset documentation, add \UL@setULdepth +% 2011: Change \dimen@ to \UL@height +% 2012: Removed \let\par garbage +% 2017: Remove \makerobust +% 2019: Handle \ULdepth better. Some tweaks. +% +% Send problem reports to asnd@triumf.ca +% +% test integrity: +% brackets: round, square, curly, angle: () [] {} <> +% backslash, slash, vertical, at, dollar, and: \ / | @ $ & +% hat, grave, acute (apostrophe), quote, tilde, under: ^ ` ' " ~ _ diff --git a/docker/Dockerfile b/docker/Dockerfile new file mode 100644 index 0000000..65ed58e --- /dev/null +++ b/docker/Dockerfile @@ -0,0 +1,14 @@ +FROM ubuntu:latest + +RUN apt update && apt install -y \ + make \ + pandoc \ + curl \ + python3.10-venv + + +RUN DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \ + texlive-xetex \ + lmodern \ + texlive + diff --git a/docker/HOWTO b/docker/HOWTO new file mode 100644 index 0000000..d5e507d --- /dev/null +++ b/docker/HOWTO @@ -0,0 +1,27 @@ + + +To use the docker image - + +1. create an image from the Dokerfile in ./docker: +# cd docker +# docker built -t . + +e.g: +IlPapersFork/docker$ docker build -t pdf-maker:latest . + +2. from the main directory run the docker: +# docker run -it --volume "${PWD}:/must have/two paths deep" +e.g +IlPapersFork$ docker run -it --volume "${PWD}:/paper/base" pdf-maker + + +3. from the command line inside the docker go to the paper directory. +e.g: +# cd /paper/base/P2022 + +4. make the pdf: +make .pdf +e.g: +# make P2022R0.pdf + +5. pray diff --git a/pdf-generator b/pdf-generator index 2a137b6..d4c30dd 160000 --- a/pdf-generator +++ b/pdf-generator @@ -1 +1 @@ -Subproject commit 2a137b63852a599d258ed5f665a80425bf1e0e8f +Subproject commit d4c30dd6a4b8c9c35cad6d61ae59007843b23664 diff --git "a/\327\242\327\223\327\233\327\225\327\237 \327\240\327\224\327\234\327\231\327\235 \327\234\327\247\327\221\327\225\327\246\327\252 \327\224\327\236\327\250\327\220\327\224 \327\224\327\231\327\251\327\250\327\220\327\234\327\231\327\252 WG21.pdf" "b/\327\242\327\223\327\233\327\225\327\237 \327\240\327\224\327\234\327\231\327\235 \327\234\327\247\327\221\327\225\327\246\327\252 \327\224\327\236\327\250\327\220\327\224 \327\224\327\231\327\251\327\250\327\220\327\234\327\231\327\252 WG21.pdf" new file mode 100644 index 0000000..1587289 Binary files /dev/null and "b/\327\242\327\223\327\233\327\225\327\237 \327\240\327\224\327\234\327\231\327\235 \327\234\327\247\327\221\327\225\327\246\327\252 \327\224\327\236\327\250\327\220\327\224 \327\224\327\231\327\251\327\250\327\220\327\234\327\231\327\252 WG21.pdf" differ