Fix Sample Transform pow operator (#2806)

Add test.
diff --git a/src/sampletransform.c b/src/sampletransform.c
index 7fdfb05..eaf6da5 100644
--- a/src/sampletransform.c
+++ b/src/sampletransform.c
@@ -244,24 +244,24 @@
             if (leftOperand == 0 || leftOperand == 1) {
                 return leftOperand;
             }
-            const uint32_t exponent = rightOperand > 0 ? (uint32_t)rightOperand : (uint32_t) - (int64_t)rightOperand;
-            if (exponent == 0) {
+            if (rightOperand == 0) {
                 return 1;
             }
-            if (exponent == 1) {
+            if (rightOperand == 1) {
                 return leftOperand;
             }
             if (leftOperand == -1) {
-                return (exponent % 2 == 0) ? 1 : -1;
+                return (rightOperand % 2 == 0) ? 1 : -1;
             }
-
+            if (rightOperand < 0) {
+                // L^R is in ]0:1[ here, so truncating it always gives 0.
+                return 0;
+            }
             int64_t result = leftOperand;
-            for (uint32_t i = 1; i < exponent; ++i) {
+            for (int32_t i = 1; i < rightOperand; ++i) {
                 result *= leftOperand;
-                if (result <= INT32_MIN) {
-                    return INT32_MIN;
-                } else if (result >= INT32_MAX) {
-                    return INT32_MAX;
+                if (result < INT32_MIN || result > INT32_MAX) {
+                    return (leftOperand > 0 || rightOperand % 2 == 0) ? INT32_MAX : INT32_MIN;
                 }
             }
             return (int32_t)result;
diff --git a/tests/gtest/avifsampletransformtest.cc b/tests/gtest/avifsampletransformtest.cc
index 1305380..3ee140a 100644
--- a/tests/gtest/avifsampletransformtest.cc
+++ b/tests/gtest/avifsampletransformtest.cc
@@ -64,6 +64,14 @@
   }
 };
 
+int32_t Eval(int32_t a, int32_t b, avifSampleTransformTokenType op) {
+  AvifExpression e;
+  e.AddConstant(a);
+  e.AddConstant(b);
+  e.AddOperator(op);
+  return e.Apply();
+}
+
 //------------------------------------------------------------------------------
 
 TEST(SampleTransformTest, NoExpression) {
@@ -129,6 +137,49 @@
   EXPECT_EQ(e.Apply(), 255);
 }
 
+TEST(SampleTransformTest, Pow) {
+  // Results are clamped to uint8_t.
+
+  EXPECT_EQ(Eval(-2, INT32_MIN, AVIF_SAMPLE_TRANSFORM_POW), 0);
+  EXPECT_EQ(Eval(-2, -3, AVIF_SAMPLE_TRANSFORM_POW), 0);
+  EXPECT_EQ(Eval(-2, -2, AVIF_SAMPLE_TRANSFORM_POW), 0);
+  EXPECT_EQ(Eval(-2, -1, AVIF_SAMPLE_TRANSFORM_POW), 0);
+  EXPECT_EQ(Eval(-2, 0, AVIF_SAMPLE_TRANSFORM_POW), 1);
+  EXPECT_EQ(Eval(-2, 1, AVIF_SAMPLE_TRANSFORM_POW), 0);  // -2 clamped
+  EXPECT_EQ(Eval(-2, 2, AVIF_SAMPLE_TRANSFORM_POW), 4);
+  EXPECT_EQ(Eval(-2, 3, AVIF_SAMPLE_TRANSFORM_POW), 0);  // -8 clamped
+  EXPECT_EQ(Eval(-2, INT32_MAX - 1, AVIF_SAMPLE_TRANSFORM_POW),
+            255);  // INT32_MAX clamped
+  EXPECT_EQ(Eval(-2, INT32_MAX, AVIF_SAMPLE_TRANSFORM_POW),
+            0);  // INT32_MIN clamped
+
+  EXPECT_EQ(Eval(-1, INT32_MIN, AVIF_SAMPLE_TRANSFORM_POW), 1);
+  EXPECT_EQ(Eval(-1, -3, AVIF_SAMPLE_TRANSFORM_POW), 0);  // -1 clamped
+  EXPECT_EQ(Eval(-1, -2, AVIF_SAMPLE_TRANSFORM_POW), 1);
+  EXPECT_EQ(Eval(-1, -1, AVIF_SAMPLE_TRANSFORM_POW), 0);  // -1 clamped
+  EXPECT_EQ(Eval(-1, 0, AVIF_SAMPLE_TRANSFORM_POW), 1);
+  EXPECT_EQ(Eval(-1, 1, AVIF_SAMPLE_TRANSFORM_POW), 0);  // -1 clamped
+  EXPECT_EQ(Eval(-1, 2, AVIF_SAMPLE_TRANSFORM_POW), 1);
+  EXPECT_EQ(Eval(-1, 3, AVIF_SAMPLE_TRANSFORM_POW), 0);  // -1 clamped
+  EXPECT_EQ(Eval(-1, INT32_MAX - 1, AVIF_SAMPLE_TRANSFORM_POW), 1);
+  EXPECT_EQ(Eval(-1, INT32_MAX, AVIF_SAMPLE_TRANSFORM_POW), 0);  // -1 clamped
+
+  for (int32_t v : {0, 1}) {
+    EXPECT_EQ(Eval(v, INT32_MIN, AVIF_SAMPLE_TRANSFORM_POW), v);
+    EXPECT_EQ(Eval(v, -2, AVIF_SAMPLE_TRANSFORM_POW), v);
+    EXPECT_EQ(Eval(v, -1, AVIF_SAMPLE_TRANSFORM_POW), v);
+    EXPECT_EQ(Eval(v, 0, AVIF_SAMPLE_TRANSFORM_POW), v);
+    EXPECT_EQ(Eval(v, 1, AVIF_SAMPLE_TRANSFORM_POW), v);
+    EXPECT_EQ(Eval(v, 2, AVIF_SAMPLE_TRANSFORM_POW), v);
+    EXPECT_EQ(Eval(v, INT32_MAX, AVIF_SAMPLE_TRANSFORM_POW), v);
+  }
+
+  EXPECT_EQ(Eval(-(1 << 16), 3, AVIF_SAMPLE_TRANSFORM_POW),
+            0);  // INT32_MIN clamped
+  EXPECT_EQ(Eval((1 << 16), 3, AVIF_SAMPLE_TRANSFORM_POW),
+            255);  // INT32_MAX clamped
+}
+
 //------------------------------------------------------------------------------
 
 struct Op {