LCOV - code coverage report
Current view: top level - autotest/cpp - testfloat16.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 84 84 100.0 %
Date: 2025-02-20 10:14:44 Functions: 16 16 100.0 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  * $Id$
       3             :  *
       4             :  * Project:  GDAL Core
       5             :  * Purpose:  Test GFloat16.
       6             :  * Author:   Erik Schnetter <eschnetter at perimeterinstitute.ca>
       7             :  *
       8             :  ******************************************************************************
       9             :  * Copyright (c) 2024, Even Rouault <even dot rouault at spatialys.com>
      10             :  *
      11             :  * SPDX-License-Identifier: MIT
      12             :  ****************************************************************************/
      13             : 
      14             : #include "cpl_float.h"
      15             : 
      16             : #include "gtest_include.h"
      17             : 
      18             : #include <algorithm>
      19             : #include <cmath>
      20             : 
      21             : namespace
      22             : {
      23             : 
      24           4 : TEST(TestFloat16, conversions)
      25             : {
      26        4098 :     for (int i = -2048; i <= +2048; ++i)
      27             :     {
      28        4097 :         EXPECT_EQ(GFloat16(i), static_cast<double>(i));
      29        4097 :         if (i >= -128 && i <= 127)
      30             :         {
      31         256 :             EXPECT_EQ(GFloat16(static_cast<signed char>(i)),
      32             :                       static_cast<double>(i));
      33             :         }
      34        4097 :         EXPECT_EQ(GFloat16(static_cast<short>(i)), static_cast<double>(i));
      35        4097 :         EXPECT_EQ(GFloat16(static_cast<int>(i)), static_cast<double>(i));
      36        4097 :         EXPECT_EQ(GFloat16(static_cast<long>(i)), static_cast<double>(i));
      37        4097 :         EXPECT_EQ(GFloat16(static_cast<long long>(i)), static_cast<double>(i));
      38        4097 :         if (i >= 0)
      39             :         {
      40        2049 :             if (i <= 255)
      41             :             {
      42         256 :                 EXPECT_EQ(GFloat16(static_cast<unsigned char>(i)),
      43             :                           static_cast<double>(i));
      44             :             }
      45        2049 :             EXPECT_EQ(GFloat16(static_cast<unsigned short>(i)),
      46             :                       static_cast<double>(i));
      47        2049 :             EXPECT_EQ(GFloat16(static_cast<unsigned>(i)),
      48             :                       static_cast<double>(i));
      49        2049 :             EXPECT_EQ(GFloat16(static_cast<unsigned long>(i)),
      50             :                       static_cast<double>(i));
      51        2049 :             EXPECT_EQ(GFloat16(static_cast<unsigned long long>(i)),
      52             :                       static_cast<double>(i));
      53             :         }
      54        4097 :         EXPECT_EQ(GFloat16(i), GFloat16(i));
      55        4097 :         EXPECT_EQ(GFloat16(i), static_cast<double>(i));
      56             :     }
      57             : 
      58           1 :     EXPECT_EQ(GFloat16(65504), 65504.0);
      59           1 :     EXPECT_EQ(GFloat16(-65504), -65504.0);
      60             :     // Work around the Windows compiler reporting "error C2124: divide
      61             :     // or mod by zero". See also
      62             :     // <https://stackoverflow.com/questions/3082508/msvc-erroring-on-a-divide-by-0-that-will-never-happen-fix>.
      63           1 :     volatile double zero = 0.0;
      64           1 :     EXPECT_EQ(GFloat16(1.0 / zero), 1.0 / zero);
      65           1 :     EXPECT_EQ(GFloat16(-1.0 / zero), -1.0 / zero);
      66           1 :     EXPECT_EQ(GFloat16(0.0), -0.0);
      67           1 :     EXPECT_EQ(GFloat16(-0.0), 0.0);
      68           1 : }
      69             : 
      70           4 : TEST(TestFloat16, arithmetic)
      71             : {
      72         202 :     for (int i = -100; i <= +100; ++i)
      73             :     {
      74         201 :         double x = i;
      75             : 
      76         201 :         EXPECT_EQ(+GFloat16(x), +x);
      77         201 :         EXPECT_EQ(-GFloat16(x), -x);
      78             :     }
      79             : 
      80         202 :     for (int i = -100; i <= +100; ++i)
      81             :     {
      82       40602 :         for (int j = -100; j <= +100; ++j)
      83             :         {
      84       40401 :             double x = i;
      85       40401 :             double y = j;
      86             : 
      87       40401 :             EXPECT_EQ(GFloat16(x) + GFloat16(y), x + y);
      88       40401 :             EXPECT_EQ(GFloat16(x) - GFloat16(y), x - y);
      89             :             using std::fabs;
      90       40401 :             EXPECT_NEAR(GFloat16(x) * GFloat16(y), x * y, fabs(x * y / 1024));
      91       40401 :             if (j != 0)
      92             :             {
      93       40200 :                 EXPECT_NEAR(GFloat16(x) / GFloat16(y), x / y,
      94             :                             fabs(x / y / 1024));
      95             :             }
      96             :         }
      97             :     }
      98           1 : }
      99             : 
     100           4 : TEST(TestFloat16, comparisons)
     101             : {
     102         202 :     for (int i = -100; i <= +100; ++i)
     103             :     {
     104       40602 :         for (int j = -100; j <= +100; ++j)
     105             :         {
     106       40401 :             double x = i;
     107       40401 :             double y = j;
     108             : 
     109       40401 :             EXPECT_EQ(GFloat16(x) == GFloat16(y), x == y);
     110       40401 :             EXPECT_EQ(GFloat16(x) != GFloat16(y), x != y);
     111       40401 :             EXPECT_EQ(GFloat16(x) < GFloat16(y), x < y);
     112       40401 :             EXPECT_EQ(GFloat16(x) > GFloat16(y), x > y);
     113       40401 :             EXPECT_EQ(GFloat16(x) <= GFloat16(y), x <= y);
     114       40401 :             EXPECT_EQ(GFloat16(x) >= GFloat16(y), x >= y);
     115             :         }
     116             :     }
     117           1 : }
     118             : 
     119           4 : TEST(TestFloat16, math)
     120             : {
     121         202 :     for (int i = -100; i <= +100; ++i)
     122             :     {
     123         201 :         double x = i;
     124             : 
     125             :         using std::isfinite;
     126         201 :         EXPECT_EQ(isfinite(GFloat16(x)), isfinite(x));
     127             :         using std::isinf;
     128         201 :         EXPECT_EQ(isinf(GFloat16(x)), isinf(x));
     129             :         using std::isnan;
     130         201 :         EXPECT_EQ(isnan(GFloat16(x)), isnan(x));
     131             :         using std::abs;
     132         201 :         EXPECT_EQ(abs(GFloat16(x)), abs(x));
     133             :         using std::cbrt;
     134             :         using std::fabs;
     135         201 :         EXPECT_NEAR(cbrt(GFloat16(x)), cbrt(x), fabs(cbrt(x) / 1024));
     136             :         using std::ceil;
     137         201 :         EXPECT_EQ(ceil(GFloat16(x)), ceil(x));
     138             :         using std::fabs;
     139         201 :         EXPECT_EQ(fabs(GFloat16(x)), fabs(x));
     140             :         using std::floor;
     141         201 :         EXPECT_EQ(floor(GFloat16(x)), floor(x));
     142             :         using std::round;
     143         201 :         EXPECT_EQ(round(GFloat16(x)), round(x));
     144         201 :         if (x >= 0)
     145             :         {
     146             :             using std::sqrt;
     147         101 :             EXPECT_NEAR(sqrt(GFloat16(x)), sqrt(x), fabs(sqrt(x) / 1024));
     148             :         }
     149             :     }
     150             : 
     151         202 :     for (int i = -100; i <= +100; ++i)
     152             :     {
     153       40602 :         for (int j = -100; j <= +100; ++j)
     154             :         {
     155       40401 :             double x = i;
     156       40401 :             double y = j;
     157             : 
     158             :             using std::fmax;
     159       40401 :             EXPECT_EQ(fmax(GFloat16(x), GFloat16(y)), GFloat16(fmax(x, y)));
     160             :             using std::fmin;
     161       40401 :             EXPECT_EQ(fmin(GFloat16(x), GFloat16(y)), GFloat16(fmin(x, y)));
     162             :             using std::hypot;
     163       40401 :             EXPECT_EQ(hypot(GFloat16(x), GFloat16(y)), GFloat16(hypot(x, y)));
     164             :             using std::max;
     165       40401 :             EXPECT_EQ(max(GFloat16(x), GFloat16(y)), GFloat16(max(x, y)));
     166             :             using std::min;
     167       40401 :             EXPECT_EQ(min(GFloat16(x), GFloat16(y)), GFloat16(min(x, y)));
     168             :             using std::pow;
     169       40401 :             EXPECT_EQ(pow(GFloat16(x), GFloat16(y)), GFloat16(pow(x, y)));
     170             :             using std::fabs;
     171             :             using std::isfinite;
     172       40401 :             GFloat16 r1 = GFloat16(pow(GFloat16(x), j));
     173       40401 :             GFloat16 r2 = GFloat16(pow(x, j));
     174       40401 :             if (!isfinite(r1))
     175             :             {
     176       19344 :                 EXPECT_EQ(r1, r2);
     177             :             }
     178             :             else
     179             :             {
     180       21057 :                 GFloat16 tol = (1 + fabs(r2)) / 1024;
     181       21057 :                 EXPECT_NEAR(r1, r2, tol);
     182             :             }
     183             :         }
     184             :     }
     185           1 : }
     186             : 
     187             : }  // namespace

Generated by: LCOV version 1.14