diff --git a/docs/ispc.rst b/docs/ispc.rst index f5ba673e..dc65ee2f 100644 --- a/docs/ispc.rst +++ b/docs/ispc.rst @@ -2931,23 +2931,26 @@ Function Overloading -------------------- Functions can be overloaded by parameter type. Given multiple definitions -of a function, ``ispc`` uses the following methods to try to find a match. -If a single match of a given type is found, it is used; if multiple matches -of a given type are found, an error is issued. +of a function, ``ispc`` uses the following model to choose the best function: +each conversion of two types has its cost. ``ispc`` tries to find conversion +with the smallest cost. When ``ispc`` can't find any conversion it means that +this function is not suitable. Then ``ispc`` sums costs for all arguments and +chooses the function with the smallest final cost. +Costs of type conversions placed from small to big: -* All parameter types match exactly. -* All parameter types match exactly, where any reference-type - parameters are considered equivalent to their underlying type. -* Parameters match with only type conversions that don't risk losing any - information (for example, converting an ``int16`` value to an ``int32`` - parameter value.) -* Parameters match with only promotions from ``uniform`` to ``varying`` - types. -* Parameters match using arbitrary type conversion, without changing - variability from ``uniform`` to ``varying`` (e.g., ``int`` to ``float``, - ``float`` to ``int``.) -* Parameters match using arbitrary type conversion, including also changing - variability from ``uniform`` to ``varying`` as needed. +1. Parameter types match exactly. +2. Function parameter type is reference and parameters match when any reference-type parameter are considered equivalent to their underlying type. +3. Function parameter type is const-reference and parameters match when any reference-type parameter are considered equivalent to their underlying type ignoring const attributes. +4. Parameters match exactly, except constant attributes. [NO CONSTANT ATTRIBUTES LATER] +5. Parameters match exactly, except reference attributes. [NO REFERENCES ATTRIBUTES LATER] +6. Parameters match with only type conversions that don't risk losing any information (for example, converting an int16 value to an int32 parameter value.) +7. Parameters match with only promotions from uniform to varying types. +8. Parameters match using arbitrary type conversion, without changing variability from uniform to varying (e.g., int to float, float to int.) +9. Parameters match with widening and promotions from uniform to varying types. (combination of "6" and "7") +10. Parameters match using arbitrary type conversion, including also changing variability from uniform to varying. + +* If function parameter type is reference and neither "2" nor "3" aren't suitable, function is not suitable +* If "10" isn't suitable, function is not suitable Re-establishing The Execution Mask diff --git a/expr.cpp b/expr.cpp index 1544be53..b7d6e657 100644 --- a/expr.cpp +++ b/expr.cpp @@ -8091,23 +8091,6 @@ lGetOverloadCandidateMessage(const std::vector &funcs, } -static bool -lIsMatchToNonConstReference(const Type *callType, const Type *funcArgType) { - return (CastType(funcArgType) && - (funcArgType->IsConstType() == false) && - Type::Equal(callType, funcArgType->GetReferenceTarget())); -} - - -static bool -lIsMatchToNonConstReferenceUnifToVarying(const Type *callType, - const Type *funcArgType) { - return (CastType(funcArgType) && - (funcArgType->IsConstType() == false) && - Type::Equal(callType->GetAsVaryingType(), - funcArgType->GetReferenceTarget())); -} - /** Helper function used for function overload resolution: returns true if converting the argument to the call type only requires a type conversion that won't lose information. Otherwise return false. @@ -8154,31 +8137,6 @@ lIsMatchWithTypeWidening(const Type *callType, const Type *funcArgType) { } -/** Helper function used for function overload resolution: returns true if - the call argument type and the function argument type match if we only - do a uniform -> varying type conversion but otherwise have exactly the - same type. - */ -static bool -lIsMatchWithUniformToVarying(const Type *callType, const Type *funcArgType) { - return (callType->IsUniformType() && - funcArgType->IsVaryingType() && - Type::EqualIgnoringConst(callType->GetAsVaryingType(), funcArgType)); -} - - -/** Helper function used for function overload resolution: returns true if - we can type convert from the call argument type to the function - argument type, but without doing a uniform -> varying conversion. - */ -static bool -lIsMatchWithTypeConvSameVariability(const Type *callType, - const Type *funcArgType) { - return (CanConvertTypes(callType, funcArgType) && - (callType->GetVariability() == funcArgType->GetVariability())); -} - - /* Returns the set of function overloads that are potential matches, given argCount values being passed as arguments to the function call. */ @@ -8249,11 +8207,12 @@ FunctionSymbolExpr::computeOverloadCost(const FunctionType *ftype, if (Type::Equal(callType, fargType)) // Perfect match: no cost + // Step "1" from documentation costSum += 0; else if (argCouldBeNULL && (*argCouldBeNULL)[i] && lArgIsPointerType(fargType)) - // Passing NULL to a pointer-typed parameter is also a no-cost - // operation + // Passing NULL to a pointer-typed parameter is also a no-cost operation + // Step "1" from documentation costSum += 0; else { // If the argument is a compile-time constant, we'd like to @@ -8261,32 +8220,82 @@ FunctionSymbolExpr::computeOverloadCost(const FunctionType *ftype, // cost if it wasn't--so scale up the cost when this isn't the // case.. if (argIsConstant == NULL || (*argIsConstant)[i] == false) - costScale *= 128; + costScale *= 512; - // For convenience, normalize to non-const types (except for - // references, where const-ness matters). For all other types, - // we're passing by value anyway, so const doesn't matter. - const Type *callTypeNC = callType, *fargTypeNC = fargType; - if (CastType(callType) == NULL) - callTypeNC = callType->GetAsNonConstType(); - if (CastType(fargType) == NULL) - fargTypeNC = fargType->GetAsNonConstType(); - - if (Type::Equal(callTypeNC, fargTypeNC)) - // Exact match (after dealing with references, above) - costSum += 1 * costScale; - // note: orig fargType for the next two... - else if (lIsMatchToNonConstReference(callTypeNC, fargType)) + if (CastType(fargType)) { + // Here we completely handle the case where fargType is reference. + if (callType->IsConstType() && !fargType->IsConstType()) { + // It is forbidden to pass const object to non-const reference (cvf -> vfr) + return -1; + } + if (!callType->IsConstType() && fargType->IsConstType()) { + // It is possible to pass (vf -> cvfr) + // but it is worse than (vf -> vfr) or (cvf -> cvfr) + // Step "3" from documentation + costSum += 2 * costScale; + } + if (!Type::Equal(callType->GetReferenceTarget()->GetAsNonConstType(), + fargType->GetReferenceTarget()->GetAsNonConstType())) { + // Types under references must be equal completely. + // vd -> vfr or vd -> cvfr are forbidden. (Although clang allows vd -> cvfr case.) + return -1; + } + // penalty for equal types under reference (vf -> vfr is worse than vf -> vf) + // Step "2" from documentation costSum += 2 * costScale; - else if (lIsMatchToNonConstReferenceUnifToVarying(callTypeNC, fargType)) - costSum += 4 * costScale; - else if (lIsMatchWithTypeWidening(callTypeNC, fargTypeNC)) + continue; + } + const Type *callTypeNP = callType; + if (CastType(callType)) { + callTypeNP = callType->GetReferenceTarget(); + // we can treat vfr as vf for callType with some penalty + // Step "5" from documentation + costSum += 2 * costScale; + } + + // Now we deal with references, so we can normalize to non-const types + // because we're passing by value anyway, so const doesn't matter. + const Type *callTypeNC = callTypeNP, *fargTypeNC = fargType; + callTypeNC = callTypeNP->GetAsNonConstType(); + fargTypeNC = fargType->GetAsNonConstType(); + + // Now we forget about constants and references! + if (Type::Equal(callTypeNC, fargTypeNC)) { + // The best case: vf -> vf. + // Step "4" from documentation + costSum += 1 * costScale; + continue; + } + if (lIsMatchWithTypeWidening(callTypeNC, fargTypeNC)) { + // A little bit worse case: vf -> vd. + // Step "6" from documentation costSum += 8 * costScale; - else if (lIsMatchWithUniformToVarying(callTypeNC, fargTypeNC)) - costSum += 16 * costScale; - else if (lIsMatchWithTypeConvSameVariability(callTypeNC, fargTypeNC)) - costSum += 32 * costScale; - else if (CanConvertTypes(callTypeNC, fargTypeNC)) + continue; + } + if (fargType->IsVaryingType() && callType->IsUniformType()) { + // Here we deal with brodcasting uniform to varying. + // callType - varying and fargType - uniform is forbidden. + if (Type::Equal(callTypeNC->GetAsVaryingType(), fargTypeNC)) { + // uf -> vf is better than uf -> ui or uf -> ud + // Step "7" from documentation + costSum += 16 * costScale; + continue; + } + if (lIsMatchWithTypeWidening(callTypeNC->GetAsVaryingType(), fargTypeNC)) { + // uf -> vd is better than uf -> vi (128 < 128 + 64) + // but worse than uf -> ui (128 > 64) + // Step "9" from documentation + costSum += 128 * costScale; + continue; + } + // 128 + 64 is the max. uf -> vi is the worst case. + // Step "10" from documentation + costSum += 128 * costScale; + } + if (CanConvertTypes(callTypeNC, fargTypeNC)) + // two cases: the worst is 128 + 64: uf -> vi and + // the only 64: (64 < 128) uf -> ui worse than uf -> vd + // Step "8" from documentation costSum += 64 * costScale; else // Failure--no type conversion possible... diff --git a/tests/ref-overloads.ispc b/tests/ref-overloads.ispc new file mode 100644 index 00000000..961af36d --- /dev/null +++ b/tests/ref-overloads.ispc @@ -0,0 +1,93 @@ +/////////////////////////VARYING +//int A011(varying float f){return 0;} int A011(varying float& f){return 1;} int A011(varying const float& f){return 2;} +//int A011(varying double f){return 3;} int A011(varying int f){return 4;} int A011(uniform float f){return 5;} +//int A011(uniform float& f){return 6;} int A011(uniform const float& f){return 7;} int A011(uniform double f){return 8;} int A011(uniform int f){return 9;} + +int A013(varying const float& f){return 2;} int A013(varying double f){return 3;} int A013(varying int f){return 4;} +int A013(uniform float f){return 5;} int A013(uniform float& f){return 6;} int A013(uniform const float& f){return 7;} +int A013(uniform double f){return 8;} int A013(uniform int f){return 9;} + +int A014(varying double f){return 3;} int A014(varying int f){return 4;} +int A014(uniform float f){return 5;} int A014(uniform float& f){return 6;} int A014(uniform const float& f){return 7;} +int A014(uniform double f){return 8;} int A014(uniform int f){return 9;} + +int A015(varying int f){return 4;} int A015(uniform float f){return 5;} +int A015(uniform float& f){return 6;} int A015(uniform const float& f){return 7;} +int A015(uniform double f){return 8;} int A015(uniform int f){return 9;} + +int A032(varying float& f){return 1;} int A032(varying double f){return 3;} int A032(varying int f){return 4;} +int A032(uniform float f){return 5;} int A032(uniform float& f){return 6;} int A032(uniform const float& f){return 7;} +int A032(uniform double f){return 8;} int A032(uniform int f){return 9;} + +int A033(varying int f){return 4;} +int A033(uniform float f){return 5;} int A033(uniform float& f){return 6;} int A033(uniform const float& f){return 7;} +int A033(uniform double f){return 8;} int A033(uniform int f){return 9;} + +/////////////////////////UNIFORM + +int A051(varying float f){return 0;} int A051(varying float& f){return 1;} int A051(varying const float& f){return 2;} +int A051(varying double f){return 3;} int A051(varying int f){return 4;} +int A051(uniform const float& f){return 7;} int A051(uniform double f){return 8;} int A051(uniform int f){return 9;} + +int A052(varying float f){return 0;} int A052(varying float& f){return 1;} int A052(varying const float& f){return 2;} +int A052(varying double f){return 3;} int A052(varying int f){return 4;} +int A052(uniform double f){return 8;} int A052(uniform int f){return 9;} + +int A053(varying float f){return 0;} int A053(varying float& f){return 1;} int A053(varying const float& f){return 2;} +int A053(varying double f){return 3;} int A053(varying int f){return 4;} int A053(uniform int f){return 9;} + +int A054(varying float& f){return 1;} int A054(varying const float& f){return 2;} +int A054(varying double f){return 3;} int A054(varying int f){return 4;} int A054(uniform int f){return 9;} + +int A055(varying float& f){return 1;} int A055(varying const float& f){return 2;} +int A055(varying double f){return 3;} int A055(varying int f){return 4;} + +int A056(varying float& f){return 1;} int A056(varying const float& f){return 2;} int A056(varying int f){return 4;} + + +export uniform int width() { return programCount; } + + + +export void f_fu(uniform float RET[], uniform float aFOO[], uniform float b) { + varying float vf = 5; + varying const float vcf = 5; + varying float& vfr = vf; + varying const float& vcfr = vf; + uniform float uf = 5; + uniform const float ucf = 5; + uniform float& ufr = uf; + uniform const float& ucfr = uf; + + if (A013(vf) != 2) {RET[programIndex] = 1; return;} + if (A014(vf) != 3) {RET[programIndex] = 2; return;} + if (A015(vf) != 4) {RET[programIndex] = 3; return;} + + if (A013(vfr) != 2) {RET[programIndex] = 4; return;} + if (A014(vfr) != 3) {RET[programIndex] = 5; return;} + if (A015(vfr) != 4) {RET[programIndex] = 6; return;} + + if (A032(vcf) != 3) {RET[programIndex] = 7; return;} + if (A033(vcf) != 4) {RET[programIndex] = 8; return;} + + if (A032(vcfr) != 3) {RET[programIndex] = 9; return;} + if (A033(vcfr) != 4) {RET[programIndex] = 10; return;} + + if (A051(uf) != 7) {RET[programIndex] = 11; return;} + if (A052(uf) != 8) {RET[programIndex] = 12; return;} + if (A053(uf) != 0) {RET[programIndex] = 13; return;} + if (A054(uf) != 9) {RET[programIndex] = 14; return;} + if (A055(uf) != 3) {RET[programIndex] = 15; return;} + if (A056(uf) != 4) {RET[programIndex] = 16; return;} + + if (A051(ufr) != 7) {RET[programIndex] = 17; return;} + if (A052(ufr) != 8) {RET[programIndex] = 18; return;} + if (A053(ufr) != 0) {RET[programIndex] = 19; return;} + if (A054(ufr) != 9) {RET[programIndex] = 20; return;} + if (A055(ufr) != 3) {RET[programIndex] = 21; return;} + if (A056(ufr) != 4) {RET[programIndex] = 22; return;} + + RET[programIndex] = 0; +} + +export void result(uniform float RET[]) { RET[programIndex] = 0; } diff --git a/tests/ref-overloads1.ispc b/tests/ref-overloads1.ispc new file mode 100644 index 00000000..114eb011 --- /dev/null +++ b/tests/ref-overloads1.ispc @@ -0,0 +1,41 @@ +void A1(float f) {} +void A2(float& f) {} +void A3(const float& f) {} +void A4(double f) {} +void A5(int f) {} +void A6(uniform float f) {} +void A7(uniform float& f) {} +void A8(uniform const float& f){} +void A9(uniform double f) {} +void A0(uniform int f) {} + + + +export uniform int width() { return programCount; } + + + +export void f_fu(uniform float RET[], uniform float aFOO[], uniform float b) { + varying float vf = 5; + varying const float vcf = 5; + varying float& vfr = vf; + varying const float& vcfr = vf; + uniform float uf = 5; + uniform const float ucf = 5; + uniform float& ufr = uf; + uniform const float& ucfr = uf; + + A1(vf); A1(vcf); A1(vfr); A1(vcfr); A1(uf); A1(ucf); A1(ufr); A1(ucfr); + A2(vf); A2(vfr); + A3(vf); A3(vcf); A3(vfr); A3(vcfr); + A4(vf); A4(vcf); A4(vfr); A4(vcfr); A4(uf); A4(ucf); A4(ufr); A4(ucfr); + A5(vf); A5(vcf); A5(vfr); A5(vcfr); A5(uf); A5(ucf); A5(ufr); A5(ucfr); + A6(uf); A6(ucf); A6(ufr); A6(ucfr); + A7(uf); A7(ufr); + A8(uf); A8(ucf); A8(ufr); A8(ucfr); + A9(uf); A9(ucf); A9(ufr); A9(ucfr); + A0(uf); A0(ucf); A0(ufr); A0(ucfr); + RET[programIndex] = 1; +} + +export void result(uniform float RET[]) { RET[programIndex] = 1; } diff --git a/tests/ref-overloads2.ispc b/tests/ref-overloads2.ispc new file mode 100644 index 00000000..a8a7152a --- /dev/null +++ b/tests/ref-overloads2.ispc @@ -0,0 +1,54 @@ +void A01(varying float f){} void A01(varying float& f){} void A01(varying const float& f){} void A01(varying double f){} void A01(varying int f){} + void A02(varying float& f){} void A02(varying const float& f){} void A02(varying double f){} void A02(varying int f){} +void A03(varying float f){} void A03(varying const float& f){} void A03(varying double f){} void A03(varying int f){} +void A04(varying float f){} void A04(varying float& f){} void A04(varying double f){} void A04(varying int f){} +void A05(varying float f){} void A05(varying float& f){} void A05(varying const float& f){} void A05(varying int f){} +void A06(varying float f){} void A06(varying float& f){} void A06(varying const float& f){} void A06(varying double f){} + +void A07(varying float f){} void A07(varying float& f){} void A07(varying const float& f){} void A07(varying double f){} void A07(varying int f){} +void A08(varying float f){} void A08(varying float& f){} void A08(varying const float& f){} void A08(varying double f){} void A08(varying int f){} +void A09(varying float f){} void A09(varying float& f){} void A09(varying const float& f){} void A09(varying double f){} void A09(varying int f){} +void A10(varying float f){} void A10(varying float& f){} void A10(varying const float& f){} void A10(varying double f){} void A10(varying int f){} +void A11(varying float f){} void A11(varying float& f){} void A11(varying const float& f){} void A11(varying double f){} void A11(varying int f){} + +void A01(uniform float f){} void A01(uniform float& f){} void A01(uniform const float& f){} void A01(uniform double f){} void A01(uniform int f){} +void A02(uniform float f){} void A02(uniform float& f){} void A02(uniform const float& f){} void A02(uniform double f){} void A02(uniform int f){} +void A03(uniform float f){} void A03(uniform float& f){} void A03(uniform const float& f){} void A03(uniform double f){} void A03(uniform int f){} +void A04(uniform float f){} void A04(uniform float& f){} void A04(uniform const float& f){} void A04(uniform double f){} void A04(uniform int f){} +void A05(uniform float f){} void A05(uniform float& f){} void A05(uniform const float& f){} void A05(uniform double f){} void A05(uniform int f){} +void A06(uniform float f){} void A06(uniform float& f){} void A06(uniform const float& f){} void A06(uniform double f){} void A06(uniform int f){} + + void A07(uniform float& f){} void A07(uniform const float& f){} void A07(uniform double f){} void A07(uniform int f){} +void A08(uniform float f){} void A08(uniform const float& f){} void A08(uniform double f){} void A08(uniform int f){} +void A09(uniform float f){} void A09(uniform float& f){} void A09(uniform double f){} void A09(uniform int f){} +void A10(uniform float f){} void A10(uniform float& f){} void A10(uniform const float& f){} void A10(uniform int f){} +void A11(uniform float f){} void A11(uniform float& f){} void A11(uniform const float& f){} void A11(uniform double f){} + +export uniform int width() { return programCount; } + + + +export void f_fu(uniform float RET[], uniform float aFOO[], uniform float b) { + varying float vf = 5; + varying const float vcf = 5; + varying float& vfr = vf; + varying const float& vcfr = vf; + uniform float uf = 5; + uniform const float ucf = 5; + uniform float& ufr = uf; + uniform const float& ucfr = uf; + + A01(vf); A01(vcf); A01(vfr); A01(vcfr); A01(uf); A01(ucf); A01(ufr); A01(ucfr); + A02(vf); A02(vcf); A02(vfr); A02(vcfr); A02(uf); A02(ucf); A02(ufr); A02(ucfr); + A03(vf); A03(vcf); A03(vfr); A03(vcfr); A03(uf); A03(ucf); A03(ufr); A03(ucfr); + A04(vf); A04(vcf); A04(vfr); A04(vcfr); A04(uf); A04(ucf); A04(ufr); A04(ucfr); + A05(vf); A05(vcf); A05(vfr); A05(vcfr); A05(uf); A05(ucf); A05(ufr); A05(ucfr); + A06(vf); A06(vcf); A06(vfr); A06(vcfr); A06(uf); A06(ucf); A06(ufr); A06(ucfr); + A07(vf); A07(vcf); A07(vfr); A07(vcfr); A07(uf); A07(ucf); A07(ufr); A07(ucfr); + A08(vf); A08(vcf); A08(vfr); A08(vcfr); A08(uf); A08(ucf); A08(ufr); A08(ucfr); + A09(vf); A09(vcf); A09(vfr); A09(vcfr); A09(uf); A09(ucf); A09(ufr); A09(ucfr); + A10(vf); A10(vcf); A10(vfr); A10(vcfr); A10(uf); A10(ucf); A10(ufr); A10(ucfr); + RET[programIndex] = 1; +} + +export void result(uniform float RET[]) { RET[programIndex] = 1; } diff --git a/tests/ref-overloads3.ispc b/tests/ref-overloads3.ispc new file mode 100644 index 00000000..b9529dd5 --- /dev/null +++ b/tests/ref-overloads3.ispc @@ -0,0 +1,99 @@ +int A01(varying float f){return 0;} int A01(varying float& f){return 1;} int A01(varying const float& f){return 2;} int A01(varying double f){return 3;} int A01(varying int f){return 4;} + int A02(varying float& f){return 1;} int A02(varying const float& f){return 2;} int A02(varying double f){return 3;} int A02(varying int f){return 4;} +int A03(varying float f){return 0;} int A03(varying const float& f){return 2;} int A03(varying double f){return 3;} int A03(varying int f){return 4;} +int A04(varying float f){return 0;} int A04(varying float& f){return 1;} int A04(varying double f){return 3;} int A04(varying int f){return 4;} + +int A07(varying float f){return 0;} int A07(varying float& f){return 1;} int A07(varying const float& f){return 2;} int A07(varying double f){return 3;} int A07(varying int f){return 4;} +int A08(varying float f){return 0;} int A08(varying float& f){return 1;} int A08(varying const float& f){return 2;} int A08(varying double f){return 3;} int A08(varying int f){return 4;} +int A09(varying float f){return 0;} int A09(varying float& f){return 1;} int A09(varying const float& f){return 2;} int A09(varying double f){return 3;} int A09(varying int f){return 4;} + +int A01(uniform float f){return 5;} int A01(uniform float& f){return 6;} int A01(uniform const float& f){return 7;} int A01(uniform double f){return 8;} int A01(uniform int f){return 9;} +int A02(uniform float f){return 5;} int A02(uniform float& f){return 6;} int A02(uniform const float& f){return 7;} int A02(uniform double f){return 8;} int A02(uniform int f){return 9;} +int A03(uniform float f){return 5;} int A03(uniform float& f){return 6;} int A03(uniform const float& f){return 7;} int A03(uniform double f){return 8;} int A03(uniform int f){return 9;} +int A04(uniform float f){return 5;} int A04(uniform float& f){return 6;} int A04(uniform const float& f){return 7;} int A04(uniform double f){return 8;} int A04(uniform int f){return 9;} + + int A07(uniform float& f){return 6;} int A07(uniform const float& f){return 7;} int A07(uniform double f){return 8;} int A07(uniform int f){return 9;} +int A08(uniform float f){return 5;} int A08(uniform const float& f){return 7;} int A08(uniform double f){return 8;} int A08(uniform int f){return 9;} +int A09(uniform float f){return 5;} int A09(uniform float& f){return 6;} int A09(uniform double f){return 8;} int A09(uniform int f){return 9;} + +export uniform int width() { return programCount; } + + + +export void f_fu(uniform float RET[], uniform float aFOO[], uniform float b) { + varying float vf = 5; + varying const float vcf = 5; + varying float& vfr = vf; + varying const float& vcfr = vf; + uniform float uf = 5; + uniform const float ucf = 5; + uniform float& ufr = uf; + uniform const float& ucfr = uf; + + if (A01(vf) != 0) {RET[programIndex] = 1; return;} + if (A01(vcf) != 0) {RET[programIndex] = 2; return;} + if (A01(vfr) != 1) {RET[programIndex] = 3; return;} + if (A01(vcfr)!= 2) {RET[programIndex] = 4; return;} + if (A01(uf) != 5) {RET[programIndex] = 5; return;} + if (A01(ucf) != 5) {RET[programIndex] = 6; return;} + if (A01(ufr) != 6) {RET[programIndex] = 7; return;} + if (A01(ucfr)!= 7) {RET[programIndex] = 8; return;} + + if (A02(vf) != 1) {RET[programIndex] = 9; return;} + if (A02(vcf) != 2) {RET[programIndex] = 10; return;} + if (A02(vfr) != 1) {RET[programIndex] = 11; return;} + if (A02(vcfr)!= 2) {RET[programIndex] = 12; return;} + if (A02(uf) != 5) {RET[programIndex] = 13; return;} + if (A02(ucf) != 5) {RET[programIndex] = 14; return;} + if (A02(ufr) != 6) {RET[programIndex] = 15; return;} + if (A02(ucfr)!= 7) {RET[programIndex] = 16; return;} + + if (A03(vf) != 0) {RET[programIndex] = 17; return;} + if (A03(vcf) != 0) {RET[programIndex] = 18; return;} + if (A03(vfr) != 0) {RET[programIndex] = 19; return;} + if (A03(vcfr)!= 2) {RET[programIndex] = 20; return;} + if (A03(uf) != 5) {RET[programIndex] = 21; return;} + if (A03(ucf) != 5) {RET[programIndex] = 22; return;} + if (A03(ufr) != 6) {RET[programIndex] = 23; return;} + if (A03(ucfr)!= 7) {RET[programIndex] = 24; return;} + + if (A04(vf) != 0) {RET[programIndex] = 25; return;} + if (A04(vcf) != 0) {RET[programIndex] = 26; return;} + if (A04(vfr) != 1) {RET[programIndex] = 27; return;} + if (A04(vcfr)!= 0) {RET[programIndex] = 28; return;} + if (A04(uf) != 5) {RET[programIndex] = 29; return;} + if (A04(ucf) != 5) {RET[programIndex] = 30; return;} + if (A04(ufr) != 6) {RET[programIndex] = 31; return;} + if (A04(ucfr)!= 7) {RET[programIndex] = 32; return;} + + if (A07(vf) != 0) {RET[programIndex] = 33; return;} + if (A07(vcf) != 0) {RET[programIndex] = 34; return;} + if (A07(vfr) != 1) {RET[programIndex] = 35; return;} + if (A07(vcfr)!= 2) {RET[programIndex] = 36; return;} + if (A07(uf) != 6) {RET[programIndex] = 37; return;} + if (A07(ucf) != 7) {RET[programIndex] = 38; return;} + if (A07(ufr) != 6) {RET[programIndex] = 39; return;} + if (A07(ucfr)!= 7) {RET[programIndex] = 40; return;} + + if (A08(vf) != 0) {RET[programIndex] = 41; return;} + if (A08(vcf) != 0) {RET[programIndex] = 42; return;} + if (A08(vfr) != 1) {RET[programIndex] = 43; return;} + if (A08(vcfr)!= 2) {RET[programIndex] = 44; return;} + if (A08(uf) != 5) {RET[programIndex] = 45; return;} + if (A08(ucf) != 5) {RET[programIndex] = 46; return;} + if (A08(ufr) != 5) {RET[programIndex] = 47; return;} + if (A08(ucfr)!= 7) {RET[programIndex] = 48; return;} + + if (A09(vf) != 0) {RET[programIndex] = 49; return;} + if (A09(vcf) != 0) {RET[programIndex] = 50; return;} + if (A09(vfr) != 1) {RET[programIndex] = 51; return;} + if (A09(vcfr)!= 2) {RET[programIndex] = 52; return;} + if (A09(uf) != 5) {RET[programIndex] = 53; return;} + if (A09(ucf) != 5) {RET[programIndex] = 54; return;} + if (A09(ufr) != 6) {RET[programIndex] = 55; return;} + if (A09(ucfr)!= 5) {RET[programIndex] = 56; return;} + + RET[programIndex] = 0; +} + +export void result(uniform float RET[]) { RET[programIndex] = 0; }