Home | History | Annotate | Download | only in tests
      1 /*
      2  * Copyright (C) 2012 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 <gtest/gtest.h>
     18 
     19 #include <fenv.h>
     20 #include <stdint.h>
     21 
     22 static void TestRounding(float expectation1, float expectation2) {
     23   // volatile to prevent compiler optimizations.
     24   volatile float f = 1.968750f;
     25   volatile float m = 0x1.0p23f;
     26   volatile float x = f + m;
     27   ASSERT_FLOAT_EQ(expectation1, x);
     28   x -= m;
     29   ASSERT_EQ(expectation2, x);
     30 }
     31 
     32 static void DivideByZero() {
     33   // volatile to prevent compiler optimizations.
     34   volatile float zero = 0.0f;
     35   volatile float result __attribute__((unused)) = 123.0f / zero;
     36 }
     37 
     38 TEST(fenv, fesetround_fegetround_FE_TONEAREST) {
     39   fesetround(FE_TONEAREST);
     40   ASSERT_EQ(FE_TONEAREST, fegetround());
     41   TestRounding(8388610.0f, 2.0f);
     42 }
     43 
     44 TEST(fenv, fesetround_fegetround_FE_TOWARDZERO) {
     45   fesetround(FE_TOWARDZERO);
     46   ASSERT_EQ(FE_TOWARDZERO, fegetround());
     47   TestRounding(8388609.0f, 1.0f);
     48 }
     49 
     50 TEST(fenv, fesetround_fegetround_FE_UPWARD) {
     51   fesetround(FE_UPWARD);
     52   ASSERT_EQ(FE_UPWARD, fegetround());
     53   TestRounding(8388610.0f, 2.0f);
     54 }
     55 
     56 TEST(fenv, fesetround_fegetround_FE_DOWNWARD) {
     57   fesetround(FE_DOWNWARD);
     58   ASSERT_EQ(FE_DOWNWARD, fegetround());
     59   TestRounding(8388609.0f, 1.0f);
     60 }
     61 
     62 TEST(fenv, feclearexcept_fetestexcept) {
     63   // Clearing clears.
     64   feclearexcept(FE_ALL_EXCEPT);
     65   ASSERT_EQ(0, fetestexcept(FE_ALL_EXCEPT));
     66 
     67   // Dividing by zero sets FE_DIVBYZERO.
     68   DivideByZero();
     69   int raised = fetestexcept(FE_DIVBYZERO | FE_OVERFLOW);
     70   ASSERT_TRUE((raised & FE_OVERFLOW) == 0);
     71   ASSERT_TRUE((raised & FE_DIVBYZERO) != 0);
     72 
     73   // Clearing an unset bit is a no-op.
     74   feclearexcept(FE_OVERFLOW);
     75   ASSERT_TRUE((raised & FE_OVERFLOW) == 0);
     76   ASSERT_TRUE((raised & FE_DIVBYZERO) != 0);
     77 
     78   // Clearing a set bit works.
     79   feclearexcept(FE_DIVBYZERO);
     80   ASSERT_EQ(0, fetestexcept(FE_ALL_EXCEPT));
     81 }
     82 
     83 TEST(fenv, FE_DFL_ENV_macro) {
     84   ASSERT_EQ(0, fesetenv(FE_DFL_ENV));
     85 }
     86