rsgBinaryOps.cpp revision 3c827367444ee418f129b2c238299f49d3264554
1/*------------------------------------------------------------------------- 2 * drawElements Quality Program Random Shader Generator 3 * ---------------------------------------------------- 4 * 5 * Copyright 2014 The Android Open Source Project 6 * 7 * Licensed under the Apache License, Version 2.0 (the "License"); 8 * you may not use this file except in compliance with the License. 9 * You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, software 14 * distributed under the License is distributed on an "AS IS" BASIS, 15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 * See the License for the specific language governing permissions and 17 * limitations under the License. 18 * 19 *//*! 20 * \file 21 * \brief Binary ops. 22 *//*--------------------------------------------------------------------*/ 23 24#include "rsgBinaryOps.hpp" 25#include "rsgVariableManager.hpp" 26#include "rsgUtils.hpp" 27#include "deMath.h" 28 29using std::vector; 30 31namespace rsg 32{ 33 34template <int Precedence, Associativity Assoc> 35BinaryOp<Precedence, Assoc>::BinaryOp (Token::Type operatorToken) 36 : m_operator (operatorToken) 37 , m_leftValueRange (m_type) 38 , m_rightValueRange (m_type) 39 , m_leftValueExpr (DE_NULL) 40 , m_rightValueExpr (DE_NULL) 41{ 42} 43 44template <int Precedence, Associativity Assoc> 45BinaryOp<Precedence, Assoc>::~BinaryOp (void) 46{ 47 delete m_leftValueExpr; 48 delete m_rightValueExpr; 49} 50 51template <int Precedence, Associativity Assoc> 52Expression* BinaryOp<Precedence, Assoc>::createNextChild (GeneratorState& state) 53{ 54 int leftPrec = Assoc == ASSOCIATIVITY_LEFT ? Precedence : Precedence-1; 55 int rightPrec = Assoc == ASSOCIATIVITY_LEFT ? Precedence-1 : Precedence; 56 57 if (m_rightValueExpr == DE_NULL) 58 { 59 state.pushPrecedence(rightPrec); 60 m_rightValueExpr = Expression::createRandom(state, m_rightValueRange); 61 state.popPrecedence(); 62 return m_rightValueExpr; 63 } 64 else if (m_leftValueExpr == DE_NULL) 65 { 66 state.pushPrecedence(leftPrec); 67 m_leftValueExpr = Expression::createRandom(state, m_leftValueRange); 68 state.popPrecedence(); 69 return m_leftValueExpr; 70 } 71 else 72 return DE_NULL; 73} 74 75template <int Precedence, Associativity Assoc> 76float BinaryOp<Precedence, Assoc>::getWeight (const GeneratorState& state, ConstValueRangeAccess valueRange) 77{ 78 if (state.getPrecedence() < Precedence) 79 return 0.0f; 80 81 int availableLevels = state.getShaderParameters().maxExpressionDepth - state.getExpressionDepth(); 82 83 if (valueRange.getType().isVoid()) 84 return availableLevels >= 2 ? unusedValueWeight : 0.0f; 85 86 if (availableLevels < getConservativeValueExprDepth(state, valueRange) + 1) 87 return 0.0f; 88 89 return 1.0f; 90} 91 92template <int Precedence, Associativity Assoc> 93void BinaryOp<Precedence, Assoc>::tokenize (GeneratorState& state, TokenStream& str) const 94{ 95 m_leftValueExpr->tokenize(state, str); 96 str << m_operator; 97 m_rightValueExpr->tokenize(state, str); 98} 99 100template <int Precedence, Associativity Assoc> 101void BinaryOp<Precedence, Assoc>::evaluate (ExecutionContext& execCtx) 102{ 103 m_leftValueExpr->evaluate(execCtx); 104 m_rightValueExpr->evaluate(execCtx); 105 106 ExecConstValueAccess leftVal = m_leftValueExpr->getValue(); 107 ExecConstValueAccess rightVal = m_rightValueExpr->getValue(); 108 ExecValueAccess dst = m_value.getValue(m_type); 109 110 evaluate(dst, leftVal, rightVal); 111} 112 113template <int Precedence, bool Float, bool Int, bool Bool, class ComputeValueRange, class EvaluateComp> 114BinaryVecOp<Precedence, Float, Int, Bool, ComputeValueRange, EvaluateComp>::BinaryVecOp (GeneratorState& state, Token::Type operatorToken, ConstValueRangeAccess inValueRange) 115 : BinaryOp<Precedence, ASSOCIATIVITY_LEFT>(operatorToken) 116{ 117 ValueRange valueRange = inValueRange; 118 119 if (valueRange.getType().isVoid()) 120 { 121 int availableLevels = state.getShaderParameters().maxExpressionDepth - state.getExpressionDepth(); 122 vector<VariableType::Type> baseTypes; 123 124 if (Float) baseTypes.push_back(VariableType::TYPE_FLOAT); 125 if (Int) baseTypes.push_back(VariableType::TYPE_INT); 126 if (Bool) baseTypes.push_back(VariableType::TYPE_BOOL); 127 128 VariableType::Type baseType = state.getRandom().choose<VariableType::Type>(baseTypes.begin(), baseTypes.end()); 129 int numElements = state.getRandom().getInt(1, availableLevels >= 3 ? 4 : 1); 130 131 valueRange = ValueRange(VariableType(baseType, numElements)); 132 computeRandomValueRange(state, valueRange.asAccess()); 133 } 134 135 // Choose type, allocate storage for execution 136 this->m_type = valueRange.getType(); 137 this->m_value.setStorage(this->m_type); 138 139 // Initialize storage for value ranges 140 this->m_rightValueRange = ValueRange(this->m_type); 141 this->m_leftValueRange = ValueRange(this->m_type); 142 143 VariableType::Type baseType = this->m_type.getBaseType(); 144 145 // Compute range for b that satisfies requested value range 146 for (int elemNdx = 0; elemNdx < this->m_type.getNumElements(); elemNdx++) 147 { 148 ConstValueRangeAccess dst = valueRange.asAccess().component(elemNdx); 149 ValueRangeAccess a = this->m_leftValueRange.asAccess().component(elemNdx); // \todo [2011-03-25 pyry] Commutative: randomize inputs 150 ValueRangeAccess b = this->m_rightValueRange.asAccess().component(elemNdx); 151 152 // Just pass undefined ranges 153 if ((baseType == VariableType::TYPE_FLOAT || baseType == VariableType::TYPE_INT) && isUndefinedValueRange(dst)) 154 { 155 a.getMin() = dst.getMin().value(); 156 b.getMin() = dst.getMin().value(); 157 a.getMax() = dst.getMax().value(); 158 b.getMax() = dst.getMax().value(); 159 continue; 160 } 161 162 if (baseType == VariableType::TYPE_FLOAT) 163 ComputeValueRange()(state.getRandom(), dst.getMin().asFloat(), dst.getMax().asFloat(), 164 a.getMin().asFloat(), a.getMax().asFloat(), 165 b.getMin().asFloat(), b.getMax().asFloat()); 166 else if (baseType == VariableType::TYPE_INT) 167 ComputeValueRange()(state.getRandom(), dst.getMin().asInt(), dst.getMax().asInt(), 168 a.getMin().asInt(), a.getMax().asInt(), 169 b.getMin().asInt(), b.getMax().asInt()); 170 else 171 { 172 DE_ASSERT(baseType == VariableType::TYPE_BOOL); 173 ComputeValueRange()(state.getRandom(), dst.getMin().asBool(), dst.getMax().asBool(), 174 a.getMin().asBool(), a.getMax().asBool(), 175 b.getMin().asBool(), b.getMax().asBool()); 176 } 177 } 178} 179 180template <int Precedence, bool Float, bool Int, bool Bool, class ComputeValueRange, class EvaluateComp> 181BinaryVecOp<Precedence, Float, Int, Bool, ComputeValueRange, EvaluateComp>::~BinaryVecOp (void) 182{ 183} 184 185template <int Precedence, bool Float, bool Int, bool Bool, class ComputeValueRange, class EvaluateComp> 186void BinaryVecOp<Precedence, Float, Int, Bool, ComputeValueRange, EvaluateComp>::evaluate (ExecValueAccess dst, ExecConstValueAccess a, ExecConstValueAccess b) 187{ 188 DE_ASSERT(dst.getType() == a.getType()); 189 DE_ASSERT(dst.getType() == b.getType()); 190 switch (dst.getType().getBaseType()) 191 { 192 case VariableType::TYPE_FLOAT: 193 for (int elemNdx = 0; elemNdx < dst.getType().getNumElements(); elemNdx++) 194 { 195 for (int compNdx = 0; compNdx < EXEC_VEC_WIDTH; compNdx++) 196 dst.component(elemNdx).asFloat(compNdx) = EvaluateComp()(a.component(elemNdx).asFloat(compNdx), b.component(elemNdx).asFloat(compNdx)); 197 } 198 break; 199 200 case VariableType::TYPE_INT: 201 for (int elemNdx = 0; elemNdx < dst.getType().getNumElements(); elemNdx++) 202 { 203 for (int compNdx = 0; compNdx < EXEC_VEC_WIDTH; compNdx++) 204 dst.component(elemNdx).asInt(compNdx) = EvaluateComp()(a.component(elemNdx).asInt(compNdx), b.component(elemNdx).asInt(compNdx)); 205 } 206 break; 207 208 default: 209 DE_ASSERT(DE_FALSE); // Invalid type for multiplication 210 } 211} 212 213void ComputeMulRange::operator() (de::Random& rnd, float dstMin, float dstMax, float& aMin, float& aMax, float& bMin, float& bMax) const 214{ 215 const float minScale = 0.25f; 216 const float maxScale = 2.0f; 217 const float subRangeStep = 0.25f; 218 const float scaleStep = 0.25f; 219 220 float scale = getQuantizedFloat(rnd, minScale, maxScale, scaleStep); 221 float scaledMin = dstMin/scale; 222 float scaledMax = dstMax/scale; 223 224 // Quantize scaled value range if possible 225 if (!quantizeFloatRange(scaledMin, scaledMax)) 226 { 227 // Fall back to 1.0 as a scale 228 scale = 1.0f; 229 scaledMin = dstMin; 230 scaledMax = dstMax; 231 } 232 233 float subRangeLen = getQuantizedFloat(rnd, 0.0f, scaledMax-scaledMin, subRangeStep); 234 aMin = scaledMin + getQuantizedFloat(rnd, 0.0f, (scaledMax-scaledMin)-subRangeLen, subRangeStep); 235 aMax = aMin + subRangeLen; 236 237 // Find scale range 238 bMin = scale; 239 bMax = scale; 240 for (int i = 0; i < 5; i++) 241 { 242 if (de::inBounds(aMin*(scale-i*scaleStep), dstMin, dstMax) && 243 de::inBounds(aMax*(scale-i*scaleStep), dstMin, dstMax)) 244 bMin = scale-i*scaleStep; 245 246 if (de::inBounds(aMin*(scale+i*scaleStep), dstMin, dstMax) && 247 de::inBounds(aMax*(scale+i*scaleStep), dstMin, dstMax)) 248 bMax = scale+i*scaleStep; 249 } 250 251 // Negative scale? 252 if (rnd.getBool()) 253 { 254 std::swap(aMin, aMax); 255 std::swap(bMin, bMax); 256 aMin *= -1.0f; 257 aMax *= -1.0f; 258 bMin *= -1.0f; 259 bMax *= -1.0f; 260 } 261 262#if defined(DE_DEBUG) 263 const float eps = 0.001f; 264 DE_ASSERT(aMin <= aMax && bMin <= bMax); 265 DE_ASSERT(de::inRange(aMin*bMin, dstMin-eps, dstMax+eps)); 266 DE_ASSERT(de::inRange(aMin*bMax, dstMin-eps, dstMax+eps)); 267 DE_ASSERT(de::inRange(aMax*bMin, dstMin-eps, dstMax+eps)); 268 DE_ASSERT(de::inRange(aMax*bMax, dstMin-eps, dstMax+eps)); 269#endif 270} 271 272void ComputeMulRange::operator() (de::Random& rnd, int dstMin, int dstMax, int& aMin, int& aMax, int& bMin, int& bMax) const 273{ 274 DE_UNREF(rnd); 275 aMin = dstMin; 276 aMax = dstMax; 277 bMin = 1; 278 bMax = 1; 279} 280 281MulOp::MulOp (GeneratorState& state, ConstValueRangeAccess valueRange) 282 : MulBase(state, Token::MUL, valueRange) 283{ 284} 285 286float MulOp::getWeight (const GeneratorState& state, ConstValueRangeAccess valueRange) 287{ 288 if (valueRange.getType().isVoid() || 289 valueRange.getType().isFloatOrVec() || 290 valueRange.getType().isIntOrVec()) 291 return MulBase::getWeight(state, valueRange); 292 else 293 return 0.0f; 294} 295 296template <typename T> 297void ComputeAddRange::operator() (de::Random& random, T dstMin, T dstMax, T& aMin, T& aMax, T& bMin, T& bMax) const 298{ 299 struct GetRandom 300 { 301 int operator() (de::Random& rnd, int min, int max) const { return rnd.getInt(min, max); } 302 float operator() (de::Random& rnd, float min, float max) const { return getQuantizedFloat(rnd, min, max, 0.5f); } 303 }; 304 305 T rangeLen = dstMax-dstMin; 306 T subRangeLen = GetRandom()(random, T(0), rangeLen); 307 T aOffset = GetRandom()(random, T(-8), T(8)); 308 309 aMin = dstMin+aOffset; 310 aMax = aMin+subRangeLen; 311 312 bMin = -aOffset; 313 bMax = -aOffset+(rangeLen-subRangeLen); 314 315#if defined(DE_DEBUG) 316 T eps = T(0.001); 317 DE_ASSERT(aMin <= aMax && bMin <= bMax); 318 DE_ASSERT(de::inRange(aMin+bMin, dstMin-eps, dstMax+eps)); 319 DE_ASSERT(de::inRange(aMin+bMax, dstMin-eps, dstMax+eps)); 320 DE_ASSERT(de::inRange(aMax+bMin, dstMin-eps, dstMax+eps)); 321 DE_ASSERT(de::inRange(aMax+bMax, dstMin-eps, dstMax+eps)); 322#endif 323} 324 325template <> 326void ComputeAddRange::operator()<bool> (de::Random&, bool, bool, bool&, bool&, bool&, bool&) const 327{ 328 DE_ASSERT(DE_FALSE); 329} 330 331AddOp::AddOp (GeneratorState& state, ConstValueRangeAccess valueRange) 332 : AddBase(state, Token::PLUS, valueRange) 333{ 334} 335 336float AddOp::getWeight (const GeneratorState& state, ConstValueRangeAccess valueRange) 337{ 338 if (valueRange.getType().isVoid() || 339 valueRange.getType().isFloatOrVec() || 340 valueRange.getType().isIntOrVec()) 341 return AddBase::getWeight(state, valueRange); 342 else 343 return 0.0f; 344} 345 346template <typename T> 347void ComputeSubRange::operator() (de::Random& random, T dstMin, T dstMax, T& aMin, T& aMax, T& bMin, T& bMax) const 348{ 349 struct GetRandom 350 { 351 int operator() (de::Random& rnd, int min, int max) const { return rnd.getInt(min, max); } 352 float operator() (de::Random& rnd, float min, float max) const { return getQuantizedFloat(rnd, min, max, 0.5f); } 353 }; 354 355 T rangeLen = dstMax-dstMin; 356 T subRangeLen = GetRandom()(random, T(0), rangeLen); 357 T aOffset = GetRandom()(random, T(-8), T(8)); 358 359 aMin = dstMin+aOffset; 360 aMax = aMin+subRangeLen; 361 362 bMin = aOffset-(rangeLen-subRangeLen); 363 bMax = aOffset; 364 365#if defined(DE_DEBUG) 366 T eps = T(0.001); 367 DE_ASSERT(aMin <= aMax && bMin <= bMax); 368 DE_ASSERT(de::inRange(aMin-bMin, dstMin-eps, dstMax+eps)); 369 DE_ASSERT(de::inRange(aMin-bMax, dstMin-eps, dstMax+eps)); 370 DE_ASSERT(de::inRange(aMax-bMin, dstMin-eps, dstMax+eps)); 371 DE_ASSERT(de::inRange(aMax-bMax, dstMin-eps, dstMax+eps)); 372#endif 373} 374 375template <> 376void ComputeSubRange::operator()<bool> (de::Random&, bool, bool, bool&, bool&, bool&, bool&) const 377{ 378 DE_ASSERT(DE_FALSE); 379} 380 381SubOp::SubOp (GeneratorState& state, ConstValueRangeAccess valueRange) 382 : SubBase(state, Token::MINUS, valueRange) 383{ 384} 385 386float SubOp::getWeight (const GeneratorState& state, ConstValueRangeAccess valueRange) 387{ 388 if (valueRange.getType().isVoid() || 389 valueRange.getType().isFloatOrVec() || 390 valueRange.getType().isIntOrVec()) 391 return SubBase::getWeight(state, valueRange); 392 else 393 return 0.0f; 394} 395 396template <class ComputeValueRange, class EvaluateComp> 397RelationalOp<ComputeValueRange, EvaluateComp>::RelationalOp (GeneratorState& state, Token::Type operatorToken, ConstValueRangeAccess inValueRange) 398 : BinaryOp<7, ASSOCIATIVITY_LEFT>(operatorToken) 399{ 400 ValueRange valueRange = inValueRange; 401 402 if (valueRange.getType().isVoid()) 403 { 404 valueRange = ValueRange(VariableType(VariableType::TYPE_BOOL, 1)); 405 computeRandomValueRange(state, valueRange.asAccess()); 406 } 407 408 // Choose type, allocate storage for execution 409 this->m_type = valueRange.getType(); 410 this->m_value.setStorage(this->m_type); 411 412 // Choose random input type 413 VariableType::Type inBaseTypes[] = { VariableType::TYPE_FLOAT, VariableType::TYPE_INT }; 414 VariableType::Type inBaseType = state.getRandom().choose<VariableType::Type>(&inBaseTypes[0], &inBaseTypes[DE_LENGTH_OF_ARRAY(inBaseTypes)]); 415 416 // Initialize storage for input value ranges 417 this->m_rightValueRange = ValueRange(VariableType(inBaseType, 1)); 418 this->m_leftValueRange = ValueRange(VariableType(inBaseType, 1)); 419 420 // Compute range for b that satisfies requested value range 421 { 422 bool dstMin = valueRange.getMin().asBool(); 423 bool dstMax = valueRange.getMax().asBool(); 424 ValueRangeAccess a = this->m_leftValueRange.asAccess(); 425 ValueRangeAccess b = this->m_rightValueRange.asAccess(); 426 427 if (inBaseType == VariableType::TYPE_FLOAT) 428 ComputeValueRange()(state.getRandom(), dstMin, dstMax, 429 a.getMin().asFloat(), a.getMax().asFloat(), 430 b.getMin().asFloat(), b.getMax().asFloat()); 431 else if (inBaseType == VariableType::TYPE_INT) 432 ComputeValueRange()(state.getRandom(), dstMin, dstMax, 433 a.getMin().asInt(), a.getMax().asInt(), 434 b.getMin().asInt(), b.getMax().asInt()); 435 } 436} 437 438template <class ComputeValueRange, class EvaluateComp> 439RelationalOp<ComputeValueRange, EvaluateComp>::~RelationalOp (void) 440{ 441} 442 443template <class ComputeValueRange, class EvaluateComp> 444void RelationalOp<ComputeValueRange, EvaluateComp>::evaluate (ExecValueAccess dst, ExecConstValueAccess a, ExecConstValueAccess b) 445{ 446 DE_ASSERT(a.getType() == b.getType()); 447 switch (a.getType().getBaseType()) 448 { 449 case VariableType::TYPE_FLOAT: 450 for (int compNdx = 0; compNdx < EXEC_VEC_WIDTH; compNdx++) 451 dst.asBool(compNdx) = EvaluateComp()(a.asFloat(compNdx), b.asFloat(compNdx)); 452 break; 453 454 case VariableType::TYPE_INT: 455 for (int compNdx = 0; compNdx < EXEC_VEC_WIDTH; compNdx++) 456 dst.asBool(compNdx) = EvaluateComp()(a.asInt(compNdx), b.asInt(compNdx)); 457 break; 458 459 default: 460 DE_ASSERT(DE_FALSE); 461 } 462} 463 464template <class ComputeValueRange, class EvaluateComp> 465float RelationalOp<ComputeValueRange, EvaluateComp>::getWeight (const GeneratorState& state, ConstValueRangeAccess valueRange) 466{ 467 if (!state.getProgramParameters().useComparisonOps) 468 return 0.0f; 469 470 if (valueRange.getType().isVoid() || 471 (valueRange.getType().getBaseType() == VariableType::TYPE_BOOL && valueRange.getType().getNumElements() == 1)) 472 return BinaryOp<7, ASSOCIATIVITY_LEFT>::getWeight(state, valueRange); 473 else 474 return 0.0f; 475} 476 477namespace 478{ 479 480template <typename T> T getStep (void); 481template <> inline float getStep (void) { return 0.25f; } 482template <> inline int getStep (void) { return 1; } 483 484} // anonymous 485 486template <typename T> 487void ComputeLessThanRange::operator () (de::Random& rnd, bool dstMin, bool dstMax, T& aMin, T& aMax, T& bMin, T& bMax) const 488{ 489 struct GetRandom 490 { 491 int operator() (de::Random& random, int min, int max) const { return random.getInt(min, max); } 492 float operator() (de::Random& random, float min, float max) const { return getQuantizedFloat(random, min, max, getStep<float>()); } 493 }; 494 495 // One random range 496 T rLen = GetRandom()(rnd, T(0), T(8)); 497 T rMin = GetRandom()(rnd, T(-4), T(4)); 498 T rMax = rMin+rLen; 499 500 if (dstMin == false && dstMax == true) 501 { 502 // Both values are possible, use same range for both inputs 503 aMin = rMin; 504 aMax = rMax; 505 bMin = rMin; 506 bMax = rMax; 507 } 508 else if (dstMin == true && dstMax == true) 509 { 510 // Compute range that is less than rMin..rMax 511 T aLen = GetRandom()(rnd, T(0), T(8)-rLen); 512 513 aMax = rMin - getStep<T>(); 514 aMin = aMax - aLen; 515 516 bMin = rMin; 517 bMax = rMax; 518 } 519 else 520 { 521 // Compute range that is greater than or equal to rMin..rMax 522 T aLen = GetRandom()(rnd, T(0), T(8)-rLen); 523 524 aMin = rMax; 525 aMax = aMin + aLen; 526 527 bMin = rMin; 528 bMax = rMax; 529 } 530} 531 532LessThanOp::LessThanOp (GeneratorState& state, ConstValueRangeAccess valueRange) 533 : LessThanBase(state, Token::CMP_LT, valueRange) 534{ 535} 536 537float LessThanOp::getWeight (const GeneratorState& state, ConstValueRangeAccess valueRange) 538{ 539 return LessThanBase::getWeight(state, valueRange); 540} 541 542template <typename T> 543void ComputeLessOrEqualRange::operator () (de::Random& rnd, bool dstMin, bool dstMax, T& aMin, T& aMax, T& bMin, T& bMax) const 544{ 545 struct GetRandom 546 { 547 int operator() (de::Random& random, int min, int max) const { return random.getInt(min, max); } 548 float operator() (de::Random& random, float min, float max) const { return getQuantizedFloat(random, min, max, getStep<float>()); } 549 }; 550 551 // One random range 552 T rLen = GetRandom()(rnd, T(0), T(8)); 553 T rMin = GetRandom()(rnd, T(-4), T(4)); 554 T rMax = rMin+rLen; 555 556 if (dstMin == false && dstMax == true) 557 { 558 // Both values are possible, use same range for both inputs 559 aMin = rMin; 560 aMax = rMax; 561 bMin = rMin; 562 bMax = rMax; 563 } 564 else if (dstMin == true && dstMax == true) 565 { 566 // Compute range that is less than or equal to rMin..rMax 567 T aLen = GetRandom()(rnd, T(0), T(8)-rLen); 568 569 aMax = rMin; 570 aMin = aMax - aLen; 571 572 bMin = rMin; 573 bMax = rMax; 574 } 575 else 576 { 577 // Compute range that is greater than rMin..rMax 578 T aLen = GetRandom()(rnd, T(0), T(8)-rLen); 579 580 aMin = rMax + getStep<T>(); 581 aMax = aMin + aLen; 582 583 bMin = rMin; 584 bMax = rMax; 585 } 586} 587 588LessOrEqualOp::LessOrEqualOp (GeneratorState& state, ConstValueRangeAccess valueRange) 589 : LessOrEqualBase(state, Token::CMP_LE, valueRange) 590{ 591} 592 593float LessOrEqualOp::getWeight (const GeneratorState& state, ConstValueRangeAccess valueRange) 594{ 595 return LessOrEqualBase::getWeight(state, valueRange); 596} 597 598GreaterThanOp::GreaterThanOp (GeneratorState& state, ConstValueRangeAccess valueRange) 599 : GreaterThanBase(state, Token::CMP_GT, valueRange) 600{ 601} 602 603float GreaterThanOp::getWeight (const GeneratorState& state, ConstValueRangeAccess valueRange) 604{ 605 return GreaterThanBase::getWeight(state, valueRange); 606} 607 608GreaterOrEqualOp::GreaterOrEqualOp (GeneratorState& state, ConstValueRangeAccess valueRange) 609 : GreaterOrEqualBase(state, Token::CMP_GE, valueRange) 610{ 611} 612 613float GreaterOrEqualOp::getWeight (const GeneratorState& state, ConstValueRangeAccess valueRange) 614{ 615 return GreaterOrEqualBase::getWeight(state, valueRange); 616} 617 618namespace 619{ 620 621template <bool IsEqual, typename T> 622void computeEqualityValueRange (de::Random& rnd, bool dstMin, bool dstMax, T& aMin, T& aMax, T& bMin, T& bMax) 623{ 624 if (dstMin == false && dstMax == true) 625 ComputeLessThanRange()(rnd, false, true, aMin, aMax, bMin, bMax); 626 else if (IsEqual && dstMin == false) 627 ComputeLessThanRange()(rnd, true, true, aMin, aMax, bMin, bMax); 628 else if (!IsEqual && dstMin == true) 629 ComputeLessThanRange()(rnd, true, true, aMin, aMax, bMin, bMax); 630 else 631 { 632 // Must have exactly same values. 633 struct GetRandom 634 { 635 int operator() (de::Random& random, int min, int max) const { return random.getInt(min, max); } 636 float operator() (de::Random& random, float min, float max) const { return getQuantizedFloat(random, min, max, 0.5f); } 637 }; 638 639 T val = GetRandom()(rnd, T(-1), T(1)); 640 641 aMin = val; 642 aMax = val; 643 bMin = val; 644 bMax = val; 645 } 646} 647 648template <> 649void computeEqualityValueRange<true, bool> (de::Random& rnd, bool dstMin, bool dstMax, bool& aMin, bool& aMax, bool& bMin, bool& bMax) 650{ 651 if (dstMin == false && dstMax == true) 652 { 653 aMin = false; 654 aMax = true; 655 bMin = false; 656 bMax = true; 657 } 658 else if (dstMin == false) 659 { 660 DE_ASSERT(dstMax == false); 661 bool val = rnd.getBool(); 662 663 aMin = val; 664 aMax = val; 665 bMin = !val; 666 bMax = !val; 667 } 668 else 669 { 670 DE_ASSERT(dstMin == true && dstMax == true); 671 bool val = rnd.getBool(); 672 673 aMin = val; 674 aMax = val; 675 bMin = val; 676 bMax = val; 677 } 678} 679 680template <> 681void computeEqualityValueRange<false, bool> (de::Random& rnd, bool dstMin, bool dstMax, bool& aMin, bool& aMax, bool& bMin, bool& bMax) 682{ 683 if (dstMin == false && dstMax == true) 684 computeEqualityValueRange<true>(rnd, dstMin, dstMax, aMin, aMax, bMin, bMax); 685 else 686 computeEqualityValueRange<true>(rnd, !dstMin, !dstMax, aMin, aMax, bMin, bMax); 687} 688 689} // anonymous 690 691template <bool IsEqual> 692EqualityComparisonOp<IsEqual>::EqualityComparisonOp (GeneratorState& state, ConstValueRangeAccess inValueRange) 693 : BinaryOp<8, ASSOCIATIVITY_LEFT>(IsEqual ? Token::CMP_EQ : Token::CMP_NE) 694{ 695 ValueRange valueRange = inValueRange; 696 697 if (valueRange.getType().isVoid()) 698 { 699 valueRange = ValueRange(VariableType(VariableType::TYPE_BOOL, 1)); 700 computeRandomValueRange(state, valueRange.asAccess()); 701 } 702 703 // Choose type, allocate storage for execution 704 this->m_type = valueRange.getType(); 705 this->m_value.setStorage(this->m_type); 706 707 // Choose random input type 708 VariableType::Type inBaseTypes[] = { VariableType::TYPE_FLOAT, VariableType::TYPE_INT }; 709 VariableType::Type inBaseType = state.getRandom().choose<VariableType::Type>(&inBaseTypes[0], &inBaseTypes[DE_LENGTH_OF_ARRAY(inBaseTypes)]); 710 int availableLevels = state.getShaderParameters().maxExpressionDepth - state.getExpressionDepth(); 711 int numElements = state.getRandom().getInt(1, availableLevels >= 3 ? 4 : 1); 712 713 // Initialize storage for input value ranges 714 this->m_rightValueRange = ValueRange(VariableType(inBaseType, numElements)); 715 this->m_leftValueRange = ValueRange(VariableType(inBaseType, numElements)); 716 717 // Compute range for b that satisfies requested value range 718 for (int elementNdx = 0; elementNdx < numElements; elementNdx++) 719 { 720 bool dstMin = valueRange.getMin().asBool(); 721 bool dstMax = valueRange.getMax().asBool(); 722 723 ValueRangeAccess a = this->m_leftValueRange.asAccess().component(elementNdx); 724 ValueRangeAccess b = this->m_rightValueRange.asAccess().component(elementNdx); 725 726 if (inBaseType == VariableType::TYPE_FLOAT) 727 computeEqualityValueRange<IsEqual>(state.getRandom(), dstMin, dstMax, 728 a.getMin().asFloat(), a.getMax().asFloat(), 729 b.getMin().asFloat(), b.getMax().asFloat()); 730 else if (inBaseType == VariableType::TYPE_INT) 731 computeEqualityValueRange<IsEqual>(state.getRandom(), dstMin, dstMax, 732 a.getMin().asInt(), a.getMax().asInt(), 733 b.getMin().asInt(), b.getMax().asInt()); 734 else 735 { 736 DE_ASSERT(inBaseType == VariableType::TYPE_BOOL); 737 computeEqualityValueRange<IsEqual>(state.getRandom(), dstMin, dstMax, 738 a.getMin().asBool(), a.getMax().asBool(), 739 b.getMin().asBool(), b.getMax().asBool()); 740 } 741 } 742} 743 744template <bool IsEqual> 745float EqualityComparisonOp<IsEqual>::getWeight (const GeneratorState& state, ConstValueRangeAccess valueRange) 746{ 747 if (!state.getProgramParameters().useComparisonOps) 748 return 0.0f; 749 750 // \todo [2011-06-13 pyry] Weight down cases that would force constant inputs. 751 752 if (valueRange.getType().isVoid() || 753 (valueRange.getType().getBaseType() == VariableType::TYPE_BOOL && valueRange.getType().getNumElements() == 1)) 754 return BinaryOp<8, ASSOCIATIVITY_LEFT>::getWeight(state, valueRange); 755 else 756 return 0.0f; 757} 758 759namespace 760{ 761 762template <bool IsEqual> 763struct EqualityCompare 764{ 765 template <typename T> 766 static bool compare (T a, T b); 767 static bool combine (bool a, bool b); 768}; 769 770template <> 771template <typename T> 772inline bool EqualityCompare<true>::compare (T a, T b) { return a == b; } 773 774template <> 775inline bool EqualityCompare<true>::combine (bool a, bool b) { return a && b; } 776 777template <> 778template <typename T> 779inline bool EqualityCompare<false>::compare (T a, T b) { return a != b; } 780 781template <> 782inline bool EqualityCompare<false>::combine (bool a, bool b) { return a || b; } 783 784} // anonymous 785 786template <bool IsEqual> 787void EqualityComparisonOp<IsEqual>::evaluate (ExecValueAccess dst, ExecConstValueAccess a, ExecConstValueAccess b) 788{ 789 DE_ASSERT(a.getType() == b.getType()); 790 791 792 switch (a.getType().getBaseType()) 793 { 794 case VariableType::TYPE_FLOAT: 795 for (int compNdx = 0; compNdx < EXEC_VEC_WIDTH; compNdx++) 796 { 797 bool result = IsEqual ? true : false; 798 799 for (int elemNdx = 0; elemNdx < a.getType().getNumElements(); elemNdx++) 800 result = EqualityCompare<IsEqual>::combine(result, EqualityCompare<IsEqual>::compare(a.component(elemNdx).asFloat(compNdx), b.component(elemNdx).asFloat(compNdx))); 801 802 dst.asBool(compNdx) = result; 803 } 804 break; 805 806 case VariableType::TYPE_INT: 807 for (int compNdx = 0; compNdx < EXEC_VEC_WIDTH; compNdx++) 808 { 809 bool result = IsEqual ? true : false; 810 811 for (int elemNdx = 0; elemNdx < a.getType().getNumElements(); elemNdx++) 812 result = EqualityCompare<IsEqual>::combine(result, EqualityCompare<IsEqual>::compare(a.component(elemNdx).asInt(compNdx), b.component(elemNdx).asInt(compNdx))); 813 814 dst.asBool(compNdx) = result; 815 } 816 break; 817 818 case VariableType::TYPE_BOOL: 819 for (int compNdx = 0; compNdx < EXEC_VEC_WIDTH; compNdx++) 820 { 821 bool result = IsEqual ? true : false; 822 823 for (int elemNdx = 0; elemNdx < a.getType().getNumElements(); elemNdx++) 824 result = EqualityCompare<IsEqual>::combine(result, EqualityCompare<IsEqual>::compare(a.component(elemNdx).asBool(compNdx), b.component(elemNdx).asBool(compNdx))); 825 826 dst.asBool(compNdx) = result; 827 } 828 break; 829 830 default: 831 DE_ASSERT(DE_FALSE); 832 } 833} 834 835EqualOp::EqualOp (GeneratorState& state, ConstValueRangeAccess valueRange) 836 : EqualityComparisonOp<true>(state, valueRange) 837{ 838} 839 840float EqualOp::getWeight (const GeneratorState& state, ConstValueRangeAccess valueRange) 841{ 842 return EqualityComparisonOp<true>::getWeight(state, valueRange); 843} 844 845NotEqualOp::NotEqualOp (GeneratorState& state, ConstValueRangeAccess valueRange) 846 : EqualityComparisonOp<false>(state, valueRange) 847{ 848} 849 850float NotEqualOp::getWeight (const GeneratorState& state, ConstValueRangeAccess valueRange) 851{ 852 return EqualityComparisonOp<false>::getWeight(state, valueRange); 853} 854 855} // rsg 856