Created
October 19, 2018 23:23
-
-
Save BillyONeal/087e421bc03deecaaade8b991e4ed0be to your computer and use it in GitHub Desktop.
Parallel Type Requirements Test Cases
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
struct inputType { | |
inputType() = delete; | |
/* implicit */ inputType(int) {} // so that the test can make an array | |
inputType(const inputType&) = delete; | |
inputType& operator=(const inputType&) = delete; | |
}; | |
struct bopResult { | |
bopResult() = delete; | |
/* implicit */ bopResult(int) {} | |
bopResult(const bopResult&) = delete; | |
bopResult& operator=(const bopResult&) = delete; | |
}; | |
struct intermediateType { | |
intermediateType() = delete; | |
explicit intermediateType(int) {} // so that the test can make one of these | |
explicit intermediateType(inputType&) {} // Intermediate tmp(*first) | |
explicit intermediateType(bopResult&&) {} // Intermediate tmp(binary_op((one of tmp, move(tmp), *first), *first)) | |
intermediateType(const intermediateType&) = delete; | |
intermediateType(intermediateType&&) = default; // tmp = move(tmp) | |
intermediateType& operator=(const intermediateType&) = delete; | |
intermediateType& operator=(intermediateType&&) = default; // for the exclusive versions only | |
// tmp = binary_op((one of tmp, move(tmp), *first), *first) | |
intermediateType& operator=(bopResult&&) { return *this; } | |
}; | |
struct outputType { | |
outputType() = delete; | |
/* implicit */ outputType(int) {} // so that the test can make an array | |
outputType(const outputType&) = delete; | |
outputType& operator=(const outputType&) = delete; | |
outputType& operator=(outputType&&) = delete; | |
// in the first pass | |
outputType& operator=(intermediateType&) { return *this; } | |
outputType& operator=(intermediateType&&) { return *this; } | |
// in the second pass | |
outputType& operator=(bopResult&&) { return *this; } | |
}; | |
struct typesBop { | |
// tmp = binary_op( (one of tmp, move(tmp), *first), *first) | |
bopResult operator()(intermediateType&, inputType&) { return 0; } | |
bopResult operator()(intermediateType&&, inputType&) { return 0; } | |
bopResult operator()(inputType&, inputType&) { return 0; } | |
// tmp = binary_op( (one of tmp, move(tmp)), (one of tmp, move(tmp)) ) | |
bopResult operator()(intermediateType& , intermediateType& ) { return 0; } | |
bopResult operator()(intermediateType& , intermediateType&&) { return 0; } | |
bopResult operator()(intermediateType&&, intermediateType& ) { return 0; } | |
bopResult operator()(intermediateType&&, intermediateType&&) { return 0; } | |
// *result = binary_op(tmp, move(*result)) | |
bopResult operator()(intermediateType&, outputType&&) { return 0; } | |
}; | |
void test_case_exclusive_scan_init_writes_intermediate_type() { | |
inputType input[2]{0, 0}; | |
outputType output[2]{0, 0}; | |
exclusive_scan(begin(input), end(input), output, intermediateType{0}, typesBop{}); | |
exclusive_scan(par, begin(input), end(input), output, intermediateType{0}, typesBop{}); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
struct inputType { | |
inputType() = delete; | |
/* implicit */ inputType(int) {} // so that the test can make an array | |
inputType(const inputType&) = delete; | |
inputType& operator=(const inputType&) = delete; | |
}; | |
struct bopResult { | |
bopResult() = delete; | |
/* implicit */ bopResult(int) {} | |
bopResult(const bopResult&) = delete; | |
bopResult& operator=(const bopResult&) = delete; | |
}; | |
struct intermediateType { | |
intermediateType() = delete; | |
explicit intermediateType(int) {} // so that the test can make one of these | |
explicit intermediateType(inputType&) {} // Intermediate tmp(*first) | |
explicit intermediateType(bopResult&&) {} // Intermediate tmp(binary_op((one of tmp, move(tmp), *first), *first)) | |
intermediateType(const intermediateType&) = delete; | |
intermediateType(intermediateType&&) = default; // tmp = move(tmp) | |
intermediateType& operator=(const intermediateType&) = delete; | |
intermediateType& operator=(intermediateType&&) = delete; | |
// tmp = binary_op((one of tmp, move(tmp), *first), *first) | |
intermediateType& operator=(bopResult&&) { return *this; } | |
}; | |
struct outputType { | |
outputType() = delete; | |
/* implicit */ outputType(int) {} // so that the test can make an array | |
outputType(const outputType&) = delete; | |
outputType& operator=(const outputType&) = delete; | |
outputType& operator=(outputType&&) = delete; | |
// in the first pass | |
outputType& operator=(intermediateType&) { return *this; } | |
outputType& operator=(intermediateType&&) { return *this; } | |
// in the second pass | |
outputType& operator=(bopResult&&) { return *this; } | |
}; | |
struct typesBop { | |
// tmp = binary_op( (one of tmp, move(tmp), *first), *first) | |
bopResult operator()(intermediateType&, inputType&) { return 0; } | |
bopResult operator()(intermediateType&&, inputType&) { return 0; } | |
bopResult operator()(inputType&, inputType&) { return 0; } | |
// tmp = binary_op( (one of tmp, move(tmp)), (one of tmp, move(tmp)) ) | |
bopResult operator()(intermediateType& , intermediateType& ) { return 0; } | |
bopResult operator()(intermediateType& , intermediateType&&) { return 0; } | |
bopResult operator()(intermediateType&&, intermediateType& ) { return 0; } | |
bopResult operator()(intermediateType&&, intermediateType&&) { return 0; } | |
// *result = binary_op(tmp, move(*result)) | |
bopResult operator()(intermediateType&, outputType&&) { return 0; } | |
}; | |
void test_case_inclusive_scan_init_writes_intermediate_type() { | |
inputType input[2]{0, 0}; | |
outputType output[2]{0, 0}; | |
inclusive_scan(begin(input), end(input), output, typesBop{}, intermediateType{0}); | |
inclusive_scan(par, begin(input), end(input), output, typesBop{}, intermediateType{0}); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
vector<unique_ptr<vector<unsigned int>>> get_move_only_test_data(const size_t testSize) { | |
vector<unique_ptr<vector<unsigned int>>> testData; | |
testData.reserve(testSize); | |
for (size_t idx = 0; idx < testSize; ++idx) { | |
testData.emplace_back(make_unique<vector<unsigned int>>(1, static_cast<unsigned int>(idx))); | |
} | |
return testData; | |
} | |
template<class ExPo> | |
void test_case_move_only(ExPo&& exec, const size_t testSize) { | |
// one could argue that this mutates the input which is presently disallowed by the parallel | |
// algorithms, but the standard is unclear here and if this isn't allowed, the standard | |
// is bad and should feel bad | |
auto testData = get_move_only_test_data(testSize); | |
unique_ptr<vector<unsigned int>> result = reduce(forward<ExPo>(exec), | |
make_move_iterator(testData.begin()), make_move_iterator(testData.end()), | |
make_unique<vector<unsigned int>>(), | |
[](unique_ptr<vector<unsigned int>> lhs, unique_ptr<vector<unsigned int>> rhs) { | |
lhs->insert(lhs->end(), rhs->begin(), rhs->end()); | |
return lhs; | |
}); | |
sort(result->begin(), result->end()); | |
for (size_t idx = 0; idx < testSize; ++idx) { | |
verify((*result)[idx] == idx); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
struct inputType { | |
inputType() = delete; | |
/* implicit */ inputType(int) {} // so that the test can make an array | |
inputType(const inputType&) = delete; | |
inputType& operator=(const inputType&) = delete; | |
}; | |
struct transformedType { | |
transformedType() = delete; | |
/* implicit */ transformedType(int) {} | |
transformedType(const transformedType&) = delete; | |
transformedType& operator=(const transformedType&) = delete; | |
}; | |
struct bopResult { | |
bopResult() = delete; | |
/* implicit */ bopResult(int) {} | |
bopResult(const bopResult&) = delete; | |
bopResult& operator=(const bopResult&) = delete; | |
}; | |
struct intermediateType { | |
intermediateType() = delete; | |
explicit intermediateType(int) {} // so that the test can make one of these | |
explicit intermediateType(transformedType&&) {} // Intermediate tmp(unary_op(*first)) | |
// Intermediate tmp(binary_op((one of tmp, move(tmp), unary_op(*first)), unary_op(*first))) | |
explicit intermediateType(bopResult&&) {} | |
intermediateType(const intermediateType&) = delete; | |
intermediateType(intermediateType&&) = default; // tmp = move(tmp) | |
intermediateType& operator=(const intermediateType&) = delete; | |
intermediateType& operator=(intermediateType&&) = default; | |
// tmp = binary_op((one of tmp, move(tmp), *first), *first) | |
intermediateType& operator=(bopResult&&) { return *this; } | |
}; | |
struct outputType { | |
outputType() = delete; | |
/* implicit */ outputType(int) {} // so that the test can make an array | |
outputType(const outputType&) = delete; | |
outputType& operator=(const outputType&) = delete; | |
outputType& operator=(outputType&&) = delete; | |
// in the first pass | |
outputType& operator=(intermediateType&) { return *this; } | |
outputType& operator=(intermediateType&&) { return *this; } | |
// in the second pass | |
outputType& operator=(bopResult&&) { return *this; } | |
}; | |
struct transformUop { | |
transformedType operator()(inputType&) { return 0; }; | |
}; | |
struct typesBop { | |
// tmp = binary_op( (one of tmp, move(tmp), unary_op(*first)), unary_op(*first)) | |
bopResult operator()(intermediateType&, transformedType&&) { return 0; } | |
bopResult operator()(intermediateType&&, transformedType&&) { return 0; } | |
bopResult operator()(transformedType&&, transformedType&&) { return 0; } | |
// tmp = binary_op( (one of tmp, move(tmp)), (one of tmp, move(tmp)) ) | |
bopResult operator()(intermediateType& , intermediateType& ) { return 0; } | |
bopResult operator()(intermediateType& , intermediateType&&) { return 0; } | |
bopResult operator()(intermediateType&&, intermediateType& ) { return 0; } | |
bopResult operator()(intermediateType&&, intermediateType&&) { return 0; } | |
// *result = binary_op(tmp, move(*result)) | |
bopResult operator()(intermediateType&, outputType&&) { return 0; } | |
}; | |
void test_case_transform_exclusive_scan_init_writes_intermediate_type() { | |
inputType input[2]{0, 0}; | |
outputType output[2]{0, 0}; | |
transform_exclusive_scan(begin(input), end(input), output, intermediateType{0}, typesBop{}, transformUop{}); | |
transform_exclusive_scan(par, begin(input), end(input), output, intermediateType{0}, typesBop{}, transformUop{}); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
struct inputType { | |
inputType() = delete; | |
/* implicit */ inputType(int) {} // so that the test can make an array | |
inputType(const inputType&) = delete; | |
inputType& operator=(const inputType&) = delete; | |
}; | |
struct transformedType { | |
transformedType() = delete; | |
/* implicit */ transformedType(int) {} | |
transformedType(const transformedType&) = delete; | |
transformedType& operator=(const transformedType&) = delete; | |
}; | |
struct bopResult { | |
bopResult() = delete; | |
/* implicit */ bopResult(int) {} | |
bopResult(const bopResult&) = delete; | |
bopResult& operator=(const bopResult&) = delete; | |
}; | |
struct intermediateType { | |
intermediateType() = delete; | |
explicit intermediateType(int) {} // so that the test can make one of these | |
explicit intermediateType(transformedType&&) {} // Intermediate tmp(unary_op(*first)) | |
// Intermediate tmp(binary_op((one of tmp, move(tmp), unary_op(*first)), unary_op(*first))) | |
explicit intermediateType(bopResult&&) {} | |
intermediateType(const intermediateType&) = delete; | |
intermediateType(intermediateType&&) = default; // tmp = move(tmp) | |
intermediateType& operator=(const intermediateType&) = delete; | |
intermediateType& operator=(intermediateType&&) = delete; | |
// tmp = binary_op((one of tmp, move(tmp), *first), *first) | |
intermediateType& operator=(bopResult&&) { return *this; } | |
}; | |
struct outputType { | |
outputType() = delete; | |
/* implicit */ outputType(int) {} // so that the test can make an array | |
outputType(const outputType&) = delete; | |
outputType& operator=(const outputType&) = delete; | |
outputType& operator=(outputType&&) = delete; | |
// in the first pass | |
outputType& operator=(intermediateType&) { return *this; } | |
outputType& operator=(intermediateType&&) { return *this; } | |
// in the second pass | |
outputType& operator=(bopResult&&) { return *this; } | |
}; | |
struct transformUop { | |
transformedType operator()(inputType&) { return 0; }; | |
}; | |
struct typesBop { | |
// tmp = binary_op( (one of tmp, move(tmp), unary_op(*first)), unary_op(*first)) | |
bopResult operator()(intermediateType&, transformedType&&) { return 0; } | |
bopResult operator()(intermediateType&&, transformedType&&) { return 0; } | |
bopResult operator()(transformedType&&, transformedType&&) { return 0; } | |
// tmp = binary_op( (one of tmp, move(tmp)), (one of tmp, move(tmp)) ) | |
bopResult operator()(intermediateType& , intermediateType& ) { return 0; } | |
bopResult operator()(intermediateType& , intermediateType&&) { return 0; } | |
bopResult operator()(intermediateType&&, intermediateType& ) { return 0; } | |
bopResult operator()(intermediateType&&, intermediateType&&) { return 0; } | |
// *result = binary_op(tmp, move(*result)) | |
bopResult operator()(intermediateType&, outputType&&) { return 0; } | |
}; | |
void test_case_transform_inclusive_scan_init_writes_intermediate_type() { | |
inputType input[2]{0, 0}; | |
outputType output[2]{0, 0}; | |
transform_inclusive_scan(begin(input), end(input), output, typesBop{}, transformUop{}, intermediateType{0}); | |
transform_inclusive_scan(par, begin(input), end(input), output, typesBop{}, transformUop{}, intermediateType{0}); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
vector<unique_ptr<vector<unsigned int>>> get_move_only_test_data(const size_t testSize) { | |
vector<unique_ptr<vector<unsigned int>>> testData; | |
testData.reserve(testSize); | |
for (size_t idx = 0; idx < testSize; ++idx) { | |
testData.emplace_back(make_unique<vector<unsigned int>>(1, static_cast<unsigned int>(idx))); | |
} | |
return testData; | |
} | |
// one could argue that the move-only examples mutate the input which is presently disallowed by the | |
// parallel algorithms, but the standard is unclear here and if this isn't allowed, the standard | |
// is bad and should feel bad | |
template<class ExPo> | |
void test_case_move_only_binary(ExPo&& exec, const size_t testSize) { | |
auto testData1 = get_move_only_test_data(testSize); | |
auto testData2 = get_move_only_test_data(testSize); | |
unique_ptr<vector<unsigned int>> result = transform_reduce(forward<ExPo>(exec), | |
make_move_iterator(testData1.begin()), make_move_iterator(testData1.end()), | |
make_move_iterator(testData2.begin()), | |
make_unique<vector<unsigned int>>(), | |
[](unique_ptr<vector<unsigned int>> lhs, unique_ptr<vector<unsigned int>> rhs) { | |
lhs->insert(lhs->end(), rhs->begin(), rhs->end()); | |
return lhs; | |
}, | |
[](unique_ptr<vector<unsigned int>> lhs, unique_ptr<vector<unsigned int>> rhs) { | |
verify(lhs->size() == 1); // should only be called directly on the input sequence | |
verify(rhs->size() == 1); | |
unsigned int lhsInt = (*lhs)[0]; | |
unsigned int rhsInt = (*rhs)[0]; | |
verify(lhsInt == rhsInt); | |
(*lhs)[0] = lhsInt * rhsInt; | |
return lhs; | |
}); | |
sort(result->begin(), result->end()); | |
for (size_t idx = 0; idx < testSize; ++idx) { | |
verify((*result)[idx] == idx * idx); | |
} | |
} | |
template<class ExPo> | |
void test_case_move_only(ExPo&& exec, const size_t testSize) { | |
auto testData = get_move_only_test_data(testSize); | |
unique_ptr<vector<unsigned int>> result = transform_reduce(forward<ExPo>(exec), | |
make_move_iterator(testData.begin()), make_move_iterator(testData.end()), | |
make_unique<vector<unsigned int>>(), | |
[](unique_ptr<vector<unsigned int>> lhs, unique_ptr<vector<unsigned int>> rhs) { | |
lhs->insert(lhs->end(), rhs->begin(), rhs->end()); | |
return lhs; | |
}, | |
[](unique_ptr<vector<unsigned int>> target) { | |
verify(target->size() == 1); // should only be called directly on the input sequence | |
target->back() *= 10; | |
return target; | |
}); | |
sort(result->begin(), result->end()); | |
for (size_t idx = 0; idx < testSize; ++idx) { | |
verify((*result)[idx] == idx * 10); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment