| 1 | // Licensed to the .NET Foundation under one or more agreements. | 
| 2 | // The .NET Foundation licenses this file to you under the MIT license. | 
| 3 | // See the LICENSE file in the project root for more information. | 
| 4 |  | 
| 5 | /*============================================================================ | 
| 6 | ** | 
| 7 | ** Source:  test1.c | 
| 8 | ** | 
| 9 | ** Purpose: Tests ceil with simple positive and negative values.  Also tests  | 
| 10 | **          extreme cases like extremely small values and positive and  | 
| 11 | **          negative infinity.  Makes sure that calling ceil on NaN returns  | 
| 12 | **          NaN | 
| 13 | ** | 
| 14 | **==========================================================================*/ | 
| 15 |  | 
| 16 | #include <palsuite.h> | 
| 17 |  | 
| 18 | // binary64 (double) has a machine epsilon of 2^-52 (approx. 2.22e-16). However, this  | 
| 19 | // is slightly too accurate when writing tests meant to run against libm implementations | 
| 20 | // for various platforms. 2^-50 (approx. 8.88e-16) seems to be as accurate as we can get. | 
| 21 | // | 
| 22 | // The tests themselves will take PAL_EPSILON and adjust it according to the expected result | 
| 23 | // so that the delta used for comparison will compare the most significant digits and ignore | 
| 24 | // any digits that are outside the double precision range (15-17 digits). | 
| 25 |  | 
| 26 | // For example, a test with an expect result in the format of 0.xxxxxxxxxxxxxxxxx will use | 
| 27 | // PAL_EPSILON for the variance, while an expected result in the format of 0.0xxxxxxxxxxxxxxxxx | 
| 28 | // will use PAL_EPSILON / 10 and and expected result in the format of x.xxxxxxxxxxxxxxxx will | 
| 29 | // use PAL_EPSILON * 10. | 
| 30 | #define PAL_EPSILON 8.8817841970012523e-16 | 
| 31 |  | 
| 32 | #define PAL_NAN     sqrt(-1.0) | 
| 33 | #define PAL_POSINF -log(0.0) | 
| 34 | #define PAL_NEGINF  log(0.0) | 
| 35 |  | 
| 36 | /** | 
| 37 |  * Helper test structure | 
| 38 |  */ | 
| 39 | struct test | 
| 40 | { | 
| 41 |     double value;     /* value to test the function with */ | 
| 42 |     double expected;  /* expected result */ | 
| 43 |     double variance;  /* maximum delta between the expected and actual result */ | 
| 44 | }; | 
| 45 |  | 
| 46 | /** | 
| 47 |  * validate | 
| 48 |  * | 
| 49 |  * test validation function | 
| 50 |  */ | 
| 51 | void __cdecl validate(double value, double expected, double variance) | 
| 52 | { | 
| 53 |     double result = ceil(value); | 
| 54 |  | 
| 55 |     /* | 
| 56 |      * The test is valid when the difference between result | 
| 57 |      * and expected is less than or equal to variance | 
| 58 |      */ | 
| 59 |     double delta = fabs(result - expected); | 
| 60 |  | 
| 61 |     if (delta > variance) | 
| 62 |     { | 
| 63 |         Fail("ceil(%g) returned %20.17g when it should have returned %20.17g" , | 
| 64 |              value, result, expected); | 
| 65 |     } | 
| 66 | } | 
| 67 |  | 
| 68 | /** | 
| 69 |  * validate | 
| 70 |  * | 
| 71 |  * test validation function for values returning NaN | 
| 72 |  */ | 
| 73 | void __cdecl validate_isnan(double value) | 
| 74 | { | 
| 75 |     double result = ceil(value); | 
| 76 |  | 
| 77 |     if (!_isnan(result)) | 
| 78 |     { | 
| 79 |         Fail("ceil(%g) returned %20.17g when it should have returned %20.17g" , | 
| 80 |              value, result, PAL_NAN); | 
| 81 |     } | 
| 82 | } | 
| 83 |  | 
| 84 | /** | 
| 85 |  * main | 
| 86 |  *  | 
| 87 |  * executable entry point | 
| 88 |  */ | 
| 89 | int __cdecl main(int argc, char *argv[]) | 
| 90 | { | 
| 91 |     struct test tests[] =  | 
| 92 |     { | 
| 93 |         /* value                   expected           variance */ | 
| 94 |         {  0.31830988618379067,    1,                 PAL_EPSILON * 10 },     // value:  1 / pi | 
| 95 |         {  0.43429448190325183,    1,                 PAL_EPSILON * 10 },     // value:  log10(e) | 
| 96 |         {  0.63661977236758134,    1,                 PAL_EPSILON * 10 },     // value:  2 / pi | 
| 97 |         {  0.69314718055994531,    1,                 PAL_EPSILON * 10 },     // value:  ln(2) | 
| 98 |         {  0.70710678118654752,    1,                 PAL_EPSILON * 10 },     // value:  1 / sqrt(2) | 
| 99 |         {  0.78539816339744831,    1,                 PAL_EPSILON * 10 },     // value:  pi / 4 | 
| 100 |         {  1.1283791670955126,     2,                 PAL_EPSILON * 10 },     // value:  2 / sqrt(pi) | 
| 101 |         {  1.4142135623730950,     2,                 PAL_EPSILON * 10 },     // value:  sqrt(2) | 
| 102 |         {  1.4426950408889634,     2,                 PAL_EPSILON * 10 },     // value:  log2(e) | 
| 103 |         {  1.5707963267948966,     2,                 PAL_EPSILON * 10 },     // value:  pi / 2 | 
| 104 |         {  2.3025850929940457,     3,                 PAL_EPSILON * 10 },     // value:  ln(10) | 
| 105 |         {  2.7182818284590452,     3,                 PAL_EPSILON * 10 },     // value:  e | 
| 106 |         {  3.1415926535897932,     4,                 PAL_EPSILON * 10 },     // value:  pi | 
| 107 |         {  PAL_POSINF,             PAL_POSINF,        0 } | 
| 108 |     }; | 
| 109 |  | 
| 110 |     /* PAL initialization */ | 
| 111 |     if (PAL_Initialize(argc, argv) != 0) | 
| 112 |     { | 
| 113 |         return FAIL; | 
| 114 |     } | 
| 115 |      | 
| 116 |     validate( 0,    0, PAL_EPSILON); | 
| 117 |     validate(-0.0,  0, PAL_EPSILON); | 
| 118 |      | 
| 119 |     validate( 1,    1, PAL_EPSILON * 10); | 
| 120 |     validate(-1.0, -1, PAL_EPSILON * 10); | 
| 121 |      | 
| 122 |     for (int i = 0; i < (sizeof(tests) / sizeof(struct test)); i++) | 
| 123 |     { | 
| 124 |         validate( tests[i].value, tests[i].expected,     tests[i].variance); | 
| 125 |         validate(-tests[i].value, 1 - tests[i].expected, tests[i].variance); | 
| 126 |     } | 
| 127 |      | 
| 128 |     validate_isnan(PAL_NAN); | 
| 129 |  | 
| 130 |     PAL_Terminate(); | 
| 131 |     return PASS; | 
| 132 | } | 
| 133 |  |