Selaa lähdekoodia

Merge pull request #15532 from jpmcmu/HPCC-21700

HPCC-21700 Created optimized pow expr for ints

Reviewed-by: Gavin Halliday <ghalliday@hpccsystems.com>
Merged-by: Gavin Halliday <ghalliday@hpccsystems.com>
Gavin Halliday 3 vuotta sitten
vanhempi
commit
f1bd15ea15

+ 61 - 1
ecl/hqlcpp/hqlcpp.cpp

@@ -3281,7 +3281,7 @@ void HqlCppTranslator::buildExpr(BuildCtx & ctx, IHqlExpression * expr, CHqlBoun
         doBuildExprSysFunc(ctx, expr, tgt, log10Id, options.divideByZeroAction);
         return;
     case no_power:
-        doBuildExprSysFunc(ctx, expr, tgt, powerId);
+        doBuildExprPow(ctx, expr, tgt);
         return;
     case no_fail:
         doBuildStmtFail(ctx, expr);
@@ -7487,6 +7487,66 @@ void HqlCppTranslator::doBuildAssignExecuteWhen(BuildCtx & ctx, const CHqlBoundT
     }
 }
 
+void HqlCppTranslator::doBuildExprPow(BuildCtx & ctx, IHqlExpression * expr, CHqlBoundExpr & tgt)
+{
+    assertex(expr->numChildren() == 2);
+
+    IHqlExpression * right = expr->queryChild(1);
+
+    bool notIntegerPower = !right->queryType()->isInteger();
+    if (notIntegerPower)
+    {
+        doBuildExprSysFunc(ctx, expr, tgt, powerId);
+        return;
+    }
+
+    IValue * value = right->queryValue();
+    bool notConstant = (value == nullptr);
+    if (notConstant) 
+    {
+        doBuildExprSysFunc(ctx, expr, tgt, powerId);
+        return;
+    }
+
+    __int64 rightIntVal = value->getIntValue();
+    __int64 absExp = abs(rightIntVal);
+
+    const unsigned int MAX_EXP_INLINE_VALUE = 3;
+    if (absExp > MAX_EXP_INLINE_VALUE)
+    {
+        doBuildExprSysFunc(ctx, expr, tgt, powerId);
+        return;
+    }
+
+    IHqlExpression * left = expr->queryChild(0);
+    if (rightIntVal == 0)
+    {
+        tgt.expr.setown(createConstant(expr->queryType()->castFrom(1.0)));
+    }
+    else
+    {
+        OwnedITypeInfo realType = makeRealType(DEFAULT_REAL_SIZE);
+        OwnedHqlExpr castLeft = ensureExprType(left, realType);
+
+        CHqlBoundExpr leftBound;
+        buildSimpleExpr(ctx, castLeft, leftBound);
+
+        tgt.set(leftBound);
+        for (int i = 1; i < absExp; i++)
+        {
+            tgt.expr.setown(createValue(no_mul, LINK(realType), tgt.expr.getClear(), LINK(leftBound.expr)));
+        }
+
+        if (rightIntVal < 0)
+        {
+            OwnedHqlExpr numerator = createConstant(realType->castFrom(1.0));
+            OwnedHqlExpr eclDivisor = tgt.getTranslatedExpr();
+            OwnedHqlExpr divide = createValue(no_div, LINK(realType), numerator.getClear(), LINK(eclDivisor));
+            buildExpr(ctx, divide, tgt);
+        }
+    }
+}
+
 //---------------------------------------------------------------------------
 //-- no_div --
 // also used for no_modulus

+ 1 - 0
ecl/hqlcpp/hqlcpp.ipp

@@ -1413,6 +1413,7 @@ public:
     void doBuildExprCountDict(BuildCtx & ctx, IHqlExpression * expr, CHqlBoundExpr & tgt);
     void doBuildExprCount(BuildCtx & ctx, IHqlExpression * expr, CHqlBoundExpr & tgt);
     void doBuildExprCounter(BuildCtx & ctx, IHqlExpression * expr, CHqlBoundExpr & tgt);
+    void doBuildExprPow(BuildCtx & ctx, IHqlExpression * expr, CHqlBoundExpr & tgt);
     void doBuildExprDivide(BuildCtx & ctx, IHqlExpression * expr, CHqlBoundExpr & tgt);
     void doBuildExprEmbedBody(BuildCtx & ctx, IHqlExpression * expr, CHqlBoundExpr * tgt);
     void doBuildExprEvaluate(BuildCtx & ctx, IHqlExpression * expr, CHqlBoundExpr & tgt);

+ 27 - 0
ecl/regress/power3.ecl

@@ -0,0 +1,27 @@
+person := dataset('person', { unsigned8 person_id, string1 per_sex, unsigned per_ssn, string40 per_first_name, data9 per_cid, unsigned8 xpos }, thor);
+
+zero := 0.0 : stored('zero');
+output(power(zero, -1));
+
+output(person,
+    {
+        POWER(person.person_id,0),
+        POWER(person.person_id,1),
+        POWER(person.person_id,2),
+        POWER(person.person_id,3),
+        POWER(person.person_id,4),
+        POWER(person.person_id,-1),
+        POWER(person.person_id,-2),
+        POWER(person.person_id,-3),
+        POWER(person.person_id,-4),
+
+        POWER(person.person_id,1.1),
+        POWER(person.person_id,2.1),
+        POWER(person.person_id,3.1),
+        POWER(person.person_id,4.1),
+        POWER(person.person_id,-1.1),
+        POWER(person.person_id,-2.1),
+        POWER(person.person_id,-3.1),
+        POWER(person.person_id,-4.1),
+        0
+    },'out.d00');

+ 42 - 0
testing/regress/ecl/key/power.xml

@@ -0,0 +1,42 @@
+<Dataset name='pow_0'>
+ <Row><pow_0>1.0</pow_0></Row>
+</Dataset>
+<Dataset name='pow_1'>
+ <Row><pow_1>1.123456</pow_1></Row>
+</Dataset>
+<Dataset name='pow_2'>
+ <Row><pow_2>1.262153383936</pow_2></Row>
+</Dataset>
+<Dataset name='pow_3'>
+ <Row><pow_3>1.417973792103203</pow_3></Row>
+</Dataset>
+<Dataset name='pow_4'>
+ <Row><pow_4>1.593031164581096</pow_4></Row>
+</Dataset>
+<Dataset name='pow_n1'>
+ <Row><pow_n1>0.8901105161216817</pow_n1></Row>
+</Dataset>
+<Dataset name='pow_n2'>
+ <Row><pow_n2>0.7922967309104065</pow_n2></Row>
+</Dataset>
+<Dataset name='pow_n3'>
+ <Row><pow_n3>0.7052316520721831</pow_n3></Row>
+</Dataset>
+<Dataset name='pow_n4'>
+ <Row><pow_n4>0.6277341098113171</pow_n4></Row>
+</Dataset>
+<Dataset name='pow_5'>
+ <Row><pow_5>0.0</pow_5></Row>
+</Dataset>
+<Dataset name='pow_6'>
+ <Row><pow_6>9.999999999999999e+299</pow_6></Row>
+</Dataset>
+<Dataset name='pow_6_2'>
+ <Row><pow_6_2>0.0</pow_6_2></Row>
+</Dataset>
+<Dataset name='pow_7'>
+ <Row><pow_7>0.5</pow_7></Row>
+</Dataset>
+<Dataset name='pow_8'>
+ <Row><pow_8>8.0</pow_8></Row>
+</Dataset>

+ 40 - 0
testing/regress/ecl/power.ecl

@@ -0,0 +1,40 @@
+/*##############################################################################
+
+    HPCC SYSTEMS software Copyright (C) 2022 HPCC Systems®.
+
+    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.
+############################################################################## */
+
+REAL    real_const := 1.123456;
+REAL    rVal := real_const : STORED('real_stored');
+
+OUTPUT(POWER(rVal,0), named('pow_0'));
+OUTPUT(POWER(rVal,1), named('pow_1'));
+OUTPUT(POWER(rVal,2), named('pow_2'));
+OUTPUT(POWER(rVal,3), named('pow_3'));
+OUTPUT(POWER(rVal,4), named('pow_4'));
+OUTPUT(POWER(rVal,-1), named('pow_n1'));
+OUTPUT(POWER(rVal,-2), named('pow_n2'));
+OUTPUT(POWER(rVal,-3), named('pow_n3'));
+OUTPUT(POWER(rVal,-4), named('pow_n4'));
+
+REAL    zero := 0.0 : STORED('zero');
+OUTPUT(POWER(zero, -1), named('pow_5'));
+
+REAL    nearZero := 1.0E-300 : STORED('nearZero');
+OUTPUT(POWER(nearZero, -1), named('pow_6'));
+OUTPUT(POWER(nearZero, -2), named('pow_6_2'));
+
+UNSIGNED1 uint2 := 2 :STORED('uint2');
+OUTPUT(POWER(uint2, -1), named('pow_7'));
+OUTPUT(POWER(uint2, 3), named('pow_8'));