xref: /aosp_15_r20/system/media/audio_utils/include/audio_utils/float_test_utils.h (revision b9df5ad1c9ac98a7fefaac271a55f7ae3db05414)
1 /*
2  * Copyright (C) 2024 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 <cmath>
18 #include <functional>
19 
20 namespace android::audio_utils::test {
21 
22 /*
23   Tests for float precision.
24 
25  ... w/o subnormals on an x86-64 -ffast-math -fhonor-infinities -fhonor-nans
26 
27  float32 without subnormals:
28 max_exponent: 127
29 min_exponent: -126
30 mantissa: 23
31 
32 float64 without subnormals:
33 max_exponent: 1023
34 min_exponent: -1022
35 mantissa: 52
36 
37 ... with subnormals ARM and x86-64 normal compilation
38 
39 float32 with subnormals:
40 max_exponent: 127
41 min_exponent: -149
42 mantissa: 23
43 
44 float64 with subnormals:
45 max_exponent: 1023
46 min_exponent: -1074
47 mantissa: 52
48 
49 */
50 
51 // This requires a functor that doubles the input.
52 template <typename D>
53 int test_max_exponent(const std::function<D(D)>& twice = [](D x) -> D { return x + x; }) {
54     D d = 1;
55     for (int i = 0; i < 16384; ++i) {
56         d = twice(d);
57         // std::cout << i << "  " << d << "\n";
58         if (std::isinf(d)) {
59             return i;
60         }
61     }
62     return 0;
63 }
64 
65 // This requires a functor that halves the input.
66 template <typename D>
67 int test_min_exponent(const std::function<D(D)>& half =[](D x) { return x * 0.5; } ) {
68     D d = 1;
69     for (int i = 0; i < 16384; ++i) {
70         d = half(d);
71         // std::cout << i << "  " << d << "\n";
72         if (d == 0) {
73             return -i;
74         }
75     }
76     return 0;
77 }
78 
79 // This requires a functor that increments the input.
80 template <typename D>
81 int test_mantissa(const std::function<D(D)>& inc = [](D x) { return x + 1; }) {
82     D d = 1;
83     for (int i = 0; i < 128; ++i) {
84         d = d + d;
85         // std::cout << i << "  " << d << "\n";
86         if (d == inc(d)) {
87             return i;
88         }
89     }
90     return 0;
91 }
92 
93 } // namespace android::audio_utils::test
94