blob: 9c0f8f6d6245ba080afb8ebde24df1d89675343a [file] [log] [blame]
//
// Copyright (c) 2017 The Khronos Group Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
#include "tools.h"
#include <sstream>
#include "harness/errorHelpers.h"
PrimeNumbersCollection PrimeNumbers::primeNumbers;
// Method generates prime numbers using Sieve of Eratosthenes algorithm
void PrimeNumbers::generatePrimeNumbers (unsigned int maxValue) {
primeNumbers.clear();
for (unsigned int i=2; i < maxValue; i++)
primeNumbers.push_back(i);
PrimeNumbersCollection::iterator it, it2;
it = primeNumbers.begin();
it2 = primeNumbers.begin();
unsigned int maxValueSqrt = (unsigned int)sqrt((double)maxValue);
for (; it != primeNumbers.end(); it++) {
it2 = it;
++it2;
if(*it>maxValueSqrt)
break;
for (;it2 != primeNumbers.end();)
if (*it2 % *it == 0)
it2 = primeNumbers.erase(it2);
else
++it2;
}
}
// Returns prime number for specified range
int PrimeNumbers::getPrimeNumberInRange (size_t lowerValue, size_t higherValue) {
if(lowerValue >= higherValue)
return -1;
if(primeNumbers.back() < lowerValue)
return -2;
PrimeNumbersCollection::iterator it = primeNumbers.begin();
for (; it != primeNumbers.end(); ++it) {
if (lowerValue<*it) {
if(higherValue>*it)
return *it;
else
return -3;
}
}
return -1;
}
int PrimeNumbers::getNextLowerPrimeNumber(size_t upperValue) {
size_t retVal = 1;
PrimeNumbersCollection::iterator it = primeNumbers.begin();
for (; it != primeNumbers.end(); ++it) {
if (upperValue > *it) {
retVal = *it;
} else {
break;
}
}
return retVal;
}
PrimeNumbers::Result1d PrimeNumbers::fitMaxPrime1d(size_t val1, size_t maxVal){
PrimeNumbers::Result1d result;
if (maxVal == 1) {
result.Val1 = 1;
return result;
}
while(val1 > maxVal)
{
val1 = PrimeNumbers::getNextLowerPrimeNumber(val1);
}
result.Val1 = val1;
return result;
}
PrimeNumbers::Result2d PrimeNumbers::fitMaxPrime2d(size_t val1, size_t val2, size_t productMax) {
PrimeNumbers::Result2d result;
if (productMax == 1) {
result.Val1 = 1;
result.Val2 = 1;
return result;
}
while ((val2 * val1) > productMax) {
if ((val2 > val1) && (val2 > 1)) {
val2 = PrimeNumbers::getNextLowerPrimeNumber(val2);
continue;
}
if (val1 > 1) {
val1 = PrimeNumbers::getNextLowerPrimeNumber(val1);
continue;
}
break;
}
result.Val1 = val1;
result.Val2 = val2;
return result;
}
PrimeNumbers::Result3d PrimeNumbers::fitMaxPrime3d(size_t val1, size_t val2, size_t val3, size_t productMax) {
Result3d result;
if (productMax == 1) {
result.Val1 = 1;
result.Val2 = 1;
result.Val3 = 1;
return result;
}
while ((val3 * val2 * val1) > productMax) {
if ((val3 > val2) && (val3 > val1) && (val3 > 1)) {
val3 = PrimeNumbers::getNextLowerPrimeNumber(val3);
continue;
}
if ((val2 > val1) && (val2 > 1)) {
val2 = PrimeNumbers::getNextLowerPrimeNumber(val2);
continue;
}
if (val1 > 1) {
val1 = PrimeNumbers::getNextLowerPrimeNumber(val1);
continue;
}
break;
}
result.Val1 = val1;
result.Val2 = val2;
result.Val3 = val3;
return result;
}
namespace Error {
ErrorMap::value_type rawDataErrorString[] = {
ErrorMap::value_type(ERR_GLOBAL_SIZE, "global size"),
ErrorMap::value_type(ERR_GLOBAL_WORK_OFFSET, "global work offset"),
ErrorMap::value_type(ERR_LOCAL_SIZE, "local size"),
ErrorMap::value_type(ERR_GLOBAL_ID, "global id"),
ErrorMap::value_type(ERR_LOCAL_ID, "local id"),
ErrorMap::value_type(ERR_ENQUEUED_LOCAL_SIZE, "enqueued local size"),
ErrorMap::value_type(ERR_LOCAL_SIZE, "local size"),
ErrorMap::value_type(ERR_NUM_GROUPS, "num groups"),
ErrorMap::value_type(ERR_GROUP_ID, "group id"),
ErrorMap::value_type(ERR_WORK_DIM, "work dim"),
ErrorMap::value_type(ERR_GLOBAL_BARRIER, "global barrier"),
ErrorMap::value_type(ERR_LOCAL_BARRIER, "local barrier"),
ErrorMap::value_type(ERR_GLOBAL_ATOMIC, "global atomic"),
ErrorMap::value_type(ERR_LOCAL_ATOMIC, "local atomic"),
ErrorMap::value_type(ERR_STRICT_MODE, "strict requirements failed. Wrong local work group size"),
ErrorMap::value_type(ERR_BUILD_STATUS, "build status"),
ErrorMap::value_type(ERR_UNKNOWN, "[unknown]"),
ErrorMap::value_type(ERR_DIFFERENT, "[different]"),
};
const int numElems = sizeof(rawDataErrorString)/sizeof(rawDataErrorString[0]);
ErrorMap errorString (rawDataErrorString, rawDataErrorString+numElems);
ErrorClass::ErrorClass() {
_overallNumberOfErrors = 0;
_stats.clear();
for (unsigned short i=0; i<sizeof(_errorArrayCounter)/sizeof(_errorArrayCounter[0]); i++) {
_errorArrayCounter[i] = 0;
}
}
void ErrorClass::show(Type err, std::string where, std::string additionalInfo) {
++_overallNumberOfErrors;
err = (errorString.find(err) == errorString.end())?ERR_UNKNOWN:err;
++_stats[err];
if (_overallNumberOfErrors == MAX_NUMBER_OF_PRINTED_ERRORS)
printError("\t. . . Too many errors. Application will skip printing them.");
if (_overallNumberOfErrors >= MAX_NUMBER_OF_PRINTED_ERRORS)
return;
std::string errString = "Error ";
errString += errorString[err];
errString += " appeared";
if(where.compare("") != 0) {
errString += " in ";
errString += where;
}
if(additionalInfo.compare("") != 0) {
errString += " ";
errString += additionalInfo;
}
printError(errString);
}
void ErrorClass::show(Type whatErr, std::string where, cl_ulong valueIs, cl_ulong valueExpected) {
std::ostringstream tmp;
tmp << "(is: " << valueIs << ", expected: " << valueExpected << ")";
show(whatErr, where, tmp.str());
}
void ErrorClass::show(std::string description) {
++_overallNumberOfErrors;
++_stats[ERR_DIFFERENT];
if (_overallNumberOfErrors < MAX_NUMBER_OF_PRINTED_ERRORS)
printError(description);
if (_overallNumberOfErrors == MAX_NUMBER_OF_PRINTED_ERRORS)
printError("\t. . . Too many errors. Application will skip printing them.");
}
void ErrorClass::printError(std::string errString) {
log_error ("%s\n", errString.c_str());
}
void ErrorClass::showStats() {
Type err;
log_info ("T E S T S U M M A R Y:\n");
for (ErrorStats::iterator it = _stats.begin(); it != _stats.end(); it++) {
err = (errorString.find(it->first) == errorString.end())?ERR_UNKNOWN:it->first;
std::string errName = errorString[err];
log_info("Error %s:\t%d\n", errName.c_str(), it->second);
}
log_info("Overall number of errors:\t%d\n", _overallNumberOfErrors);
}
bool ErrorClass::checkError() {
return _overallNumberOfErrors > 0;
}
// This method is required to synchronize errors counters between kernel and host
void ErrorClass::synchronizeStatsMap() {
for (unsigned short i=0; i<sizeof(_errorArrayCounter)/sizeof(_errorArrayCounter[0]); i++) {
if(_errorArrayCounter[i] == 0)
continue;
_stats[static_cast<Type>(i)] += _errorArrayCounter[i];
_overallNumberOfErrors += _errorArrayCounter[i];
}
}
}