Home | History | Annotate | Download | only in unittest
      1 /*
      2  * Copyright (C) 2017 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #include "shared.rsh"
     18 
     19 static volatile half h1;
     20 static volatile half2 h2;
     21 static volatile half3 h3;
     22 static volatile half4 h4;
     23 
     24 static volatile int i1;
     25 static volatile int2 i2;
     26 static volatile int3 i3;
     27 static volatile int4 i4;
     28 
     29 #define TEST_HN_FUNC_HN(fn) \
     30     h1 = fn(h1);            \
     31     h2 = fn(h2);            \
     32     h3 = fn(h3);            \
     33     h4 = fn(h4);
     34 
     35 #define TEST_IN_FUNC_HN(fn) \
     36     i1 = fn(h1);            \
     37     i2 = fn(h2);            \
     38     i3 = fn(h3);            \
     39     i4 = fn(h4);
     40 
     41 #define TEST_HN_FUNC_HN_HN(fn)  \
     42     h1 = fn(h1, h1);            \
     43     h2 = fn(h2, h2);            \
     44     h3 = fn(h3, h3);            \
     45     h4 = fn(h4, h4);
     46 
     47 #define TEST_HN_FUNC_HN_IN(fn)  \
     48     h1 = fn(h1, i1);            \
     49     h2 = fn(h2, i2);            \
     50     h3 = fn(h3, i3);            \
     51     h4 = fn(h4, i4);
     52 
     53 #define TEST_HN_FUNC_HN_PIN(fn) \
     54     h1 = fn(h1, (int *) &i1);   \
     55     h2 = fn(h2, (int2 *) &i2);  \
     56     h3 = fn(h3, (int3 *) &i3);  \
     57     h4 = fn(h4, (int4 *) &i4);
     58 
     59 #define TEST_HN_FUNC_HN_I(fn)  \
     60     h1 = fn(h1, i1);           \
     61     h2 = fn(h2, i1);           \
     62     h3 = fn(h3, i1);           \
     63     h4 = fn(h4, i1);
     64 
     65 #define TEST_HN_FUNC_HN_H(fn)  \
     66     h1 = fn(h1, h1);           \
     67     h2 = fn(h2, h1);           \
     68     h3 = fn(h3, h1);           \
     69     h4 = fn(h4, h1);
     70 
     71 #define TEST_HN_FUNC_H_HN(fn)  \
     72     h1 = fn(h1, h1);           \
     73     h2 = fn(h1, h2);           \
     74     h3 = fn(h1, h3);           \
     75     h4 = fn(h1, h4);           \
     76 
     77 #define TEST_HN_FUNC_HN_PHN(fn) \
     78     h1 = fn(h1, (half *) &h1);  \
     79     h2 = fn(h2, (half2 *) &h2); \
     80     h3 = fn(h3, (half3 *) &h3); \
     81     h4 = fn(h4, (half4 *) &h4); \
     82 
     83 #define TEST_HN_FUNC_HN_HN_HN(fn)   \
     84     h1 = fn(h1, h1, h1);            \
     85     h2 = fn(h2, h2, h2);            \
     86     h3 = fn(h3, h3, h3);            \
     87     h4 = fn(h4, h4, h4);
     88 
     89 #define TEST_HN_FUNC_HN_HN_H(fn)   \
     90     h1 = fn(h1, h1, h1);           \
     91     h2 = fn(h2, h2, h1);           \
     92     h3 = fn(h3, h3, h1);           \
     93     h4 = fn(h4, h4, h1);
     94 
     95 #define TEST_HN_FUNC_HN_HN_PIN(fn) \
     96     h1 = fn(h1, h1, (int *) &i1);  \
     97     h2 = fn(h2, h2, (int2 *) &i2); \
     98     h3 = fn(h3, h3, (int3 *) &i3); \
     99     h4 = fn(h4, h4, (int4 *) &i4);
    100 
    101 #define TEST_H_FUNC_HN(fn)  \
    102     h1 = fn(h1);            \
    103     h1 = fn(h2);            \
    104     h1 = fn(h3);            \
    105     h1 = fn(h4);
    106 
    107 #define TEST_H_FUNC_HN_HN(fn) \
    108     h1 = fn(h1, h1);          \
    109     h1 = fn(h2, h2);          \
    110     h1 = fn(h3, h3);          \
    111     h1 = fn(h4, h4);
    112 
    113 static bool testAPI() {
    114     TEST_HN_FUNC_HN(acos);
    115     TEST_HN_FUNC_HN(acosh);
    116     TEST_HN_FUNC_HN(acospi);
    117 
    118     TEST_HN_FUNC_HN(asin);
    119     TEST_HN_FUNC_HN(asinh);
    120     TEST_HN_FUNC_HN(asinpi);
    121 
    122     TEST_HN_FUNC_HN(atan);
    123     TEST_HN_FUNC_HN_HN(atan2);
    124     TEST_HN_FUNC_HN_HN(atan2pi);
    125     TEST_HN_FUNC_HN(atanh);
    126     TEST_HN_FUNC_HN(atanpi);
    127 
    128     TEST_HN_FUNC_HN(cbrt);
    129     TEST_HN_FUNC_HN(ceil);
    130     TEST_HN_FUNC_HN_HN(copysign);
    131 
    132     TEST_HN_FUNC_HN(cos);
    133     TEST_HN_FUNC_HN(cosh);
    134     TEST_HN_FUNC_HN(cospi);
    135 
    136     TEST_HN_FUNC_HN(degrees);
    137     TEST_HN_FUNC_HN(erf);
    138     TEST_HN_FUNC_HN(erfc);
    139     TEST_HN_FUNC_HN(exp);
    140     TEST_HN_FUNC_HN(exp10);
    141     TEST_HN_FUNC_HN(exp2);
    142     TEST_HN_FUNC_HN(expm1);
    143 
    144     TEST_HN_FUNC_HN(fabs);
    145     TEST_HN_FUNC_HN_HN(fdim);
    146     TEST_HN_FUNC_HN(floor);
    147     TEST_HN_FUNC_HN_HN_HN(fma);
    148 
    149     TEST_HN_FUNC_HN_HN(fmax);
    150     TEST_HN_FUNC_HN_H(fmax);
    151     TEST_HN_FUNC_HN_HN(fmin);
    152     TEST_HN_FUNC_HN_H(fmin);
    153     TEST_HN_FUNC_HN_HN(fmod);
    154 
    155     TEST_HN_FUNC_HN(fract);
    156     TEST_HN_FUNC_HN_PHN(fract);
    157     TEST_HN_FUNC_HN_PIN(frexp);
    158 
    159     TEST_HN_FUNC_HN_HN(hypot);
    160     TEST_IN_FUNC_HN(ilogb);
    161     TEST_HN_FUNC_HN_IN(ldexp);
    162     TEST_HN_FUNC_HN_I(ldexp);
    163     TEST_HN_FUNC_HN(lgamma);
    164     TEST_HN_FUNC_HN_PIN(lgamma);
    165 
    166     TEST_HN_FUNC_HN(log);
    167     TEST_HN_FUNC_HN(log10);
    168     TEST_HN_FUNC_HN(log1p);
    169     TEST_HN_FUNC_HN(log2);
    170     TEST_HN_FUNC_HN(logb);
    171 
    172     TEST_HN_FUNC_HN_HN_HN(mad);
    173     TEST_HN_FUNC_HN_HN(max);
    174     TEST_HN_FUNC_HN_H(max);
    175     TEST_HN_FUNC_HN_HN(min);
    176     TEST_HN_FUNC_HN_H(min);
    177     TEST_HN_FUNC_HN_HN_HN(mix);
    178     TEST_HN_FUNC_HN_HN_H(mix);
    179     TEST_HN_FUNC_HN_PHN(modf);
    180 
    181     h1 = nan_half();
    182 
    183     TEST_HN_FUNC_HN(native_acos);
    184     TEST_HN_FUNC_HN(native_acosh);
    185     TEST_HN_FUNC_HN(native_acospi);
    186 
    187     TEST_HN_FUNC_HN(native_asin);
    188     TEST_HN_FUNC_HN(native_asinh);
    189     TEST_HN_FUNC_HN(native_asinpi);
    190 
    191     TEST_HN_FUNC_HN(native_atan);
    192     TEST_HN_FUNC_HN_HN(native_atan2);
    193     TEST_HN_FUNC_HN_HN(native_atan2pi);
    194     TEST_HN_FUNC_HN(native_atanh);
    195     TEST_HN_FUNC_HN(native_atanpi);
    196 
    197     TEST_HN_FUNC_HN(native_cbrt);
    198     TEST_HN_FUNC_HN(native_cos);
    199     TEST_HN_FUNC_HN(native_cosh);
    200     TEST_HN_FUNC_HN(native_cospi);
    201 
    202     TEST_HN_FUNC_HN_HN(native_divide);
    203     TEST_HN_FUNC_HN(native_exp);
    204     TEST_HN_FUNC_HN(native_exp10);
    205     TEST_HN_FUNC_HN(native_exp2);
    206     TEST_HN_FUNC_HN(native_expm1);
    207 
    208     TEST_HN_FUNC_HN_HN(native_hypot);
    209     TEST_H_FUNC_HN(native_length);
    210     TEST_HN_FUNC_HN(native_log);
    211     TEST_HN_FUNC_HN(native_log10);
    212     TEST_HN_FUNC_HN(native_log1p);
    213     TEST_HN_FUNC_HN(native_log2);
    214 
    215     TEST_HN_FUNC_HN_HN(native_powr);
    216     TEST_HN_FUNC_HN(native_recip);
    217     TEST_HN_FUNC_HN_IN(native_rootn);
    218     TEST_HN_FUNC_HN(native_rsqrt);
    219 
    220     TEST_HN_FUNC_HN(native_sin);
    221     TEST_HN_FUNC_HN_PHN(native_sincos);
    222     TEST_HN_FUNC_HN(native_sinh);
    223     TEST_HN_FUNC_HN(native_sinpi);
    224 
    225     TEST_HN_FUNC_HN(native_tan);
    226     TEST_HN_FUNC_HN(native_tanh);
    227     TEST_HN_FUNC_HN(native_tanpi);
    228 
    229     TEST_HN_FUNC_HN_HN(nextafter);
    230     TEST_HN_FUNC_HN_HN(pow);
    231     TEST_HN_FUNC_HN_IN(pown);
    232     TEST_HN_FUNC_HN_HN(powr);
    233 
    234     TEST_HN_FUNC_HN(radians);
    235     TEST_HN_FUNC_HN_HN(remainder);
    236     TEST_HN_FUNC_HN_HN_PIN(remquo);
    237     TEST_HN_FUNC_HN(rint);
    238     TEST_HN_FUNC_HN_IN(rootn);
    239     TEST_HN_FUNC_HN(round);
    240     TEST_HN_FUNC_HN(rsqrt);
    241 
    242     TEST_HN_FUNC_HN(sign);
    243     TEST_HN_FUNC_HN(sin);
    244     TEST_HN_FUNC_HN_PHN(sincos);
    245     TEST_HN_FUNC_HN(sinh);
    246     TEST_HN_FUNC_HN(sinpi);
    247     TEST_HN_FUNC_HN(sqrt);
    248 
    249     TEST_HN_FUNC_HN_HN(step);
    250     TEST_HN_FUNC_HN_H(step);
    251     TEST_HN_FUNC_H_HN(step);
    252 
    253     TEST_HN_FUNC_HN(tan);
    254     TEST_HN_FUNC_HN(tanh);
    255     TEST_HN_FUNC_HN(tanpi);
    256 
    257     TEST_HN_FUNC_HN(tgamma);
    258     TEST_HN_FUNC_HN(trunc);
    259 
    260     // Vector math functions
    261     h3 = cross(h3, h3);
    262     h4 = cross(h4, h4);
    263 
    264     TEST_H_FUNC_HN_HN(distance);
    265     TEST_H_FUNC_HN_HN(dot);
    266     TEST_H_FUNC_HN(length);
    267     TEST_H_FUNC_HN_HN(native_distance);
    268     TEST_H_FUNC_HN(native_length);
    269     TEST_HN_FUNC_HN(native_normalize);
    270     TEST_HN_FUNC_HN(normalize);
    271     return true;
    272 }
    273 
    274 typedef union {
    275   half hval;
    276   short sval;
    277 } fp16_shape_type;
    278 
    279 /* half h = unsigned short s; */
    280 #define SET_HALF_WORD(h, s) \
    281 do {                        \
    282   fp16_shape_type fp16_u;   \
    283   fp16_u.sval = (s);        \
    284   (h) = fp16_u.hval;        \
    285 } while (0)
    286 
    287 #define VALIDATE_FREXP_HALF(inp, ref, refExp)  \
    288 do {                                           \
    289     int exp;                                   \
    290     half out = frexp(((half) inp), &exp);      \
    291     _RS_ASSERT_EQU(out, ((half) ref));         \
    292     _RS_ASSERT_EQU(exp, (refExp));             \
    293 } while (0);
    294 
    295 static bool testFrexp() {
    296     bool failed= false;
    297 
    298     VALIDATE_FREXP_HALF(0, 0, 0);
    299     VALIDATE_FREXP_HALF(-0, -0, 0);
    300     VALIDATE_FREXP_HALF(1, 0.5, 1);
    301     VALIDATE_FREXP_HALF(0.25, 0.5, -1);
    302     VALIDATE_FREXP_HALF(1.5, 0.75, 1);
    303     VALIDATE_FREXP_HALF(1.99, 0.995, 1);
    304 
    305     return !failed;
    306 }
    307 
    308 // Place sentinel values around the *intPart paramter to modf to ensure that
    309 // the call writes to just the 2 bytes pointed-to by the paramter.
    310 #define VALIDATE_MODF_HALF(inp, ref, refIntPart)     \
    311 do {                                                 \
    312     half intPart[3];                                 \
    313     intPart[0] = (half) 42.0f;                       \
    314     intPart[2] = (half) 3.14f;                       \
    315     half out = modf(((half) inp), &intPart[1]);      \
    316     _RS_ASSERT_EQU(out, ((half) ref));               \
    317     _RS_ASSERT_EQU(intPart[1], ((half) refIntPart)); \
    318     _RS_ASSERT_EQU(intPart[0], (half) 42.0f);        \
    319     _RS_ASSERT_EQU(intPart[2], (half) 3.14f);        \
    320 } while (0);
    321 
    322 static bool testModf() {
    323     bool failed = false;
    324 
    325     VALIDATE_MODF_HALF(0.5, 0.5, 0.0);
    326     VALIDATE_MODF_HALF(1.5, 0.5, 1.0);
    327     VALIDATE_MODF_HALF(100.5625, 0.5625, 100.0);
    328 
    329     VALIDATE_MODF_HALF(-0.5, -0.5, -0.0);
    330     VALIDATE_MODF_HALF(-1.5, -0.5, -1.0);
    331     VALIDATE_MODF_HALF(-100.5625, -0.5625, -100.0);
    332 
    333     return !failed;
    334 }
    335 
    336 static bool testNextAfter() {
    337     half zero, minSubNormal, maxSubNormal, minNormal, infinity;
    338     half negativeZero, negativeInfinity;
    339     half negativeMinSubNormal, negativeMaxSubNormal, negativeMinNormal;
    340 
    341     // TODO Define these constants so the SET_HALF_WORD macro is unnecessary.
    342     SET_HALF_WORD(zero, 0x0000);
    343     SET_HALF_WORD(minSubNormal, 0x0001);
    344     SET_HALF_WORD(maxSubNormal, 0x03ff);
    345     SET_HALF_WORD(minNormal, 0x0400);
    346     SET_HALF_WORD(infinity, 0x7c00);
    347 
    348     SET_HALF_WORD(negativeZero, 0x7000);
    349     SET_HALF_WORD(negativeMinSubNormal, 0x8001);
    350     SET_HALF_WORD(negativeMaxSubNormal, 0x83ff);
    351     SET_HALF_WORD(negativeMinNormal, 0x8400);
    352     SET_HALF_WORD(negativeInfinity, 0xfc00);
    353 
    354     // Number of normal fp16 values:
    355     //   All-zero exponent is for zero and subnormals.  All-one exponent is for
    356     //   Infinity and NaN.  Hence number of possible values for exponent = 30
    357     //
    358     //   No. of possible values for mantissa = 2 ^ 10 = 1024
    359     //
    360     //   Number of positive, non-zero and normal fp16 values = 30 * 1024 = 30720
    361     //   Number of negative, non-zero and normal fp16 values = 30 * 1024 = 30720
    362     //
    363     //   The following tests call nextafter in a loop starting at infinity
    364     //   towards the smallest normal and vice versa (for +ve and -ve) and verify
    365     //   that the number of loop iterations is 30720.
    366 
    367     const unsigned int numDistinctExpected = 30720;
    368     const unsigned int maxSteps = 31000;
    369 
    370     unsigned int numDistinct;
    371     half h, toward;
    372 
    373     for (h = minNormal, toward = infinity, numDistinct = 0;
    374             numDistinct < maxSteps && h != toward; numDistinct ++) {
    375         h = nextafter(h, toward);
    376     }
    377     if (numDistinct != numDistinctExpected)
    378         return false;
    379 
    380     for (h = infinity, toward = minNormal, numDistinct = 0;
    381             numDistinct < maxSteps && h != toward; numDistinct ++) {
    382         h = nextafter(h, toward);
    383     }
    384     if (numDistinct != numDistinctExpected)
    385         return false;
    386 
    387     for (h = negativeMinNormal, toward = negativeInfinity, numDistinct = 0;
    388             numDistinct < maxSteps && h != toward; numDistinct ++) {
    389         h = nextafter(h, toward);
    390     }
    391     if (numDistinct != numDistinctExpected)
    392         return false;
    393 
    394     for (h = negativeInfinity, toward = negativeMinNormal, numDistinct = 0;
    395             numDistinct < maxSteps && h != toward; numDistinct ++) {
    396         h = nextafter(h, toward);
    397     }
    398     if (numDistinct != numDistinctExpected)
    399         return false;
    400 
    401     // Test nextafter at the boundary of subnormal numbers.  Since RenderScript
    402     // doesn't require implementations to handle FP16 subnormals correctly,
    403     // allow nextafter to return a valid normal number that satisfies the
    404     // constraints of nextafter.
    405 
    406     // nextafter(0, infinity) = minnormal or minsubnormal
    407     h = nextafter(zero, infinity);
    408     if (h != minSubNormal && h != minNormal)
    409         return false;
    410     h = nextafter(zero, negativeInfinity);
    411     if (h != negativeMinSubNormal && h != negativeMinNormal)
    412         return false;
    413 
    414     // nextafter(minNormal, negativeInfinity) = maxSubNormal or zero
    415     h = nextafter(minNormal, negativeInfinity);
    416     if (h != maxSubNormal && h != zero)
    417         return false;
    418     h = nextafter(negativeMinNormal, infinity);
    419     if (h != negativeMaxSubNormal && h != negativeZero)
    420         return false;
    421 
    422     return true;
    423 }
    424 
    425 static bool testIlogb() {
    426     bool failed = false;
    427 
    428     // Test ilogb for 0, +/- infininty and NaN
    429     half infinity, negativeInfinity;
    430     SET_HALF_WORD(infinity, 0x7c00);
    431     SET_HALF_WORD(negativeInfinity, 0xfc00);
    432 
    433     _RS_ASSERT_EQU(ilogb((half) 0), 0x80000000);
    434     _RS_ASSERT_EQU(ilogb((half) -0), 0x80000000);
    435     _RS_ASSERT_EQU(ilogb(infinity), 0x7fffffff);
    436     _RS_ASSERT_EQU(ilogb(negativeInfinity), 0x7fffffff);
    437     _RS_ASSERT_EQU(ilogb(nan_half()), 0x7fffffff);
    438 
    439     // ilogb(2^n) = n.  Test at the boundary on either side of 2^n.
    440     // Don't test subnormal numbers as implementations are not expected to
    441     // handle them.
    442     _RS_ASSERT_EQU(ilogb((half) 0.24), -3);
    443     _RS_ASSERT_EQU(ilogb((half) 0.26), -2);
    444     _RS_ASSERT_EQU(ilogb((half) 0.49), -2);
    445     _RS_ASSERT_EQU(ilogb((half) 0.51), -1);
    446     _RS_ASSERT_EQU(ilogb((half) 0.99), -1);
    447     _RS_ASSERT_EQU(ilogb((half) 1.01), 0);
    448     _RS_ASSERT_EQU(ilogb((half) 1.99), 0);
    449     _RS_ASSERT_EQU(ilogb((half) 2.01), 1);
    450     _RS_ASSERT_EQU(ilogb((half) 1023), 9);
    451     _RS_ASSERT_EQU(ilogb((half) 1025), 10);
    452 
    453     // Result is same irrespective of sign.
    454     _RS_ASSERT_EQU(ilogb((half) -0.24), -3);
    455     _RS_ASSERT_EQU(ilogb((half) -0.26), -2);
    456     _RS_ASSERT_EQU(ilogb((half) -0.49), -2);
    457     _RS_ASSERT_EQU(ilogb((half) -0.51), -1);
    458     _RS_ASSERT_EQU(ilogb((half) -0.99), -1);
    459     _RS_ASSERT_EQU(ilogb((half) -1.01), 0);
    460     _RS_ASSERT_EQU(ilogb((half) -1.99), 0);
    461     _RS_ASSERT_EQU(ilogb((half) -2.01), 1);
    462     _RS_ASSERT_EQU(ilogb((half) -1023), 9);
    463     _RS_ASSERT_EQU(ilogb((half) -1025), 10);
    464 
    465     return !failed;
    466 }
    467 
    468 void testFp16Math() {
    469     bool success = true;
    470 
    471     success &= testAPI();
    472     success &= testFrexp();
    473     success &= testModf();
    474     success &= testNextAfter();
    475     success &= testIlogb();
    476 
    477     if (success) {
    478         rsDebug("PASSED", 0);
    479     } else {
    480         rsDebug("FAILED", 0);
    481     }
    482 
    483     if (success) {
    484         rsSendToClientBlocking(RS_MSG_TEST_PASSED);
    485     } else {
    486         rsSendToClientBlocking(RS_MSG_TEST_FAILED);
    487     }
    488 }
    489