1 
2 //
3 // This source file is part of appleseed.
4 // Visit https://appleseedhq.net/ for additional information and resources.
5 //
6 // This software is released under the MIT license.
7 //
8 // Copyright (c) 2010-2013 Francois Beaune, Jupiter Jazz Limited
9 // Copyright (c) 2014-2018 Francois Beaune, The appleseedhq Organization
10 //
11 // Permission is hereby granted, free of charge, to any person obtaining a copy
12 // of this software and associated documentation files (the "Software"), to deal
13 // in the Software without restriction, including without limitation the rights
14 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15 // copies of the Software, and to permit persons to whom the Software is
16 // furnished to do so, subject to the following conditions:
17 //
18 // The above copyright notice and this permission notice shall be included in
19 // all copies or substantial portions of the Software.
20 //
21 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
27 // THE SOFTWARE.
28 //
29 
30 // appleseed.foundation headers.
31 #include "foundation/math/rng/distribution.h"
32 #include "foundation/math/rng/mersennetwister.h"
33 #include "foundation/utility/bitmask.h"
34 #include "foundation/utility/test.h"
35 
36 // Standard headers.
37 #include <cstddef>
38 
39 using namespace foundation;
40 
TEST_SUITE(Foundation_Utility_BitMask2)41 TEST_SUITE(Foundation_Utility_BitMask2)
42 {
43     TEST_CASE(Clear_SetsAllBitsToZero)
44     {
45         BitMask2 bitmask(2, 2);
46 
47         bitmask.clear();
48 
49         EXPECT_EQ(0, bitmask.get(0, 0));
50         EXPECT_EQ(0, bitmask.get(1, 0));
51         EXPECT_EQ(0, bitmask.get(0, 1));
52         EXPECT_EQ(0, bitmask.get(1, 1));
53     }
54 
55     TEST_CASE(Set_SetsBit)
56     {
57         BitMask2 bitmask(2, 2);
58         bitmask.clear();
59 
60         bitmask.set(1, 1);
61 
62         EXPECT_TRUE(bitmask.is_set(1, 1));
63     }
64 
65     TEST_CASE(Clear_ClearsBit)
66     {
67         BitMask2 bitmask(2, 2);
68         bitmask.clear();
69 
70         bitmask.set(1, 1);
71         bitmask.clear(1, 1);
72 
73         EXPECT_TRUE(bitmask.is_clear(1, 1));
74     }
75 
76     TEST_CASE(Clear_PreservesOtherBits)
77     {
78         BitMask2 bitmask(2, 2);
79         bitmask.clear();
80 
81         bitmask.set(0, 0);
82         bitmask.clear(1, 0);
83 
84         EXPECT_TRUE(bitmask.is_set(0, 0));
85     }
86 
87     bool are_equal(const BitMask2& bitmask, const bool* values)
88     {
89         for (size_t y = 0; y < bitmask.get_height(); ++y)
90         {
91             for (size_t x = 0; x < bitmask.get_width(); ++x)
92             {
93                 if (bitmask.get(x, y) != values[y * bitmask.get_width() + x])
94                     return false;
95             }
96         }
97 
98         return true;
99     }
100 
101     TEST_CASE(StressTest)
102     {
103         const size_t Width = 17;
104         const size_t Height = 9;
105 
106         bool values[Width * Height];
107 
108         for (size_t i = 0; i < Width * Height; ++i)
109             values[i] = false;
110 
111         BitMask2 bitmask(Width, Height);
112         bitmask.clear();
113 
114         MersenneTwister rng;
115 
116         for (size_t i = 0; i < 1000; ++i)
117         {
118             const size_t x = rand_int1(rng, 0, Width - 1);
119             const size_t y = rand_int1(rng, 0, Height - 1);
120             const bool value = rand_int1(rng, 0, 1) == 1;
121 
122             values[y * Width + x] = value;
123             bitmask.set(x, y, value);
124 
125             const bool equal = are_equal(bitmask, values);
126             ASSERT_TRUE(equal);
127         }
128     }
129 }
130