Skip to content

Commit 75c8eac

Browse files
Common: added AlignUpToPowerOfTwo and AlignDownToPowerOfTwo functions
1 parent 477edd8 commit 75c8eac

File tree

2 files changed

+75
-2
lines changed

2 files changed

+75
-2
lines changed

Common/interface/Align.hpp

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2019-2022 Diligent Graphics LLC
2+
* Copyright 2019-2025 Diligent Graphics LLC
33
* Copyright 2015-2019 Egor Yusov
44
*
55
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -33,6 +33,7 @@
3333
#include <cstdint>
3434

3535
#include "../../Platforms/Basic/interface/DebugUtilities.hpp"
36+
#include "../../Platforms/interface/PlatformMisc.hpp"
3637

3738
namespace Diligent
3839
{
@@ -100,4 +101,23 @@ inline typename std::conditional<sizeof(T1) >= sizeof(T2), T1, T2>::type AlignUp
100101
return tmp - (tmp % static_cast<T>(alignment));
101102
}
102103

104+
template <typename T>
105+
inline typename std::enable_if<std::is_unsigned<T>::value, T>::type AlignUpToPowerOfTwo(T Val)
106+
{
107+
using MSBType = typename std::conditional<std::is_same<T, Uint64>::value, Uint64, Uint32>::type;
108+
109+
return Val == 0 || IsPowerOfTwo(Val) ?
110+
Val :
111+
(T{1} << static_cast<T>(PlatformMisc::GetMSB(MSBType{Val}) + 1));
112+
}
113+
template <typename T>
114+
inline typename std::enable_if<std::is_unsigned<T>::value, T>::type AlignDownToPowerOfTwo(T Val)
115+
{
116+
using MSBType = typename std::conditional<std::is_same<T, Uint64>::value, Uint64, Uint32>::type;
117+
118+
return Val == 0 || IsPowerOfTwo(Val) ?
119+
Val :
120+
(T{1} << static_cast<T>(PlatformMisc::GetMSB(MSBType{Val})));
121+
}
122+
103123
} // namespace Diligent

Tests/DiligentCoreTest/src/Common/AlignTest.cpp

Lines changed: 54 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2019-2022 Diligent Graphics LLC
2+
* Copyright 2019-2025 Diligent Graphics LLC
33
* Copyright 2015-2019 Egor Yusov
44
*
55
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -194,4 +194,57 @@ TEST(Common_Align, AlignUpNonPw2)
194194
EXPECT_EQ(AlignUpNonPw2((Uint64{1} << 63) + 1, Uint64{1024}), (Uint64{1} << 63) + 1024);
195195
}
196196

197+
template <typename T>
198+
void TestAlignUpToPowerOfTwo()
199+
{
200+
EXPECT_EQ(AlignUpToPowerOfTwo(T{0}), T{0});
201+
EXPECT_EQ(AlignUpToPowerOfTwo(T{1}), T{1});
202+
EXPECT_EQ(AlignUpToPowerOfTwo(T{2}), T{2});
203+
204+
for (T i = 2; i < sizeof(T) * 8 - 1; ++i)
205+
{
206+
T Pw2 = T{1} << i;
207+
T Test1 = Pw2 - T{1};
208+
T Test2 = (Pw2 >> T{1}) + T{1};
209+
EXPECT_EQ(AlignUpToPowerOfTwo(Pw2), Pw2);
210+
EXPECT_EQ(AlignUpToPowerOfTwo(Test1), Pw2);
211+
EXPECT_EQ(AlignUpToPowerOfTwo(Test2), Pw2);
212+
}
213+
}
214+
215+
TEST(Common_Align, AlignUpToPowerOfTwo)
216+
{
217+
TestAlignUpToPowerOfTwo<Uint8>();
218+
TestAlignUpToPowerOfTwo<Uint16>();
219+
TestAlignUpToPowerOfTwo<Uint32>();
220+
TestAlignUpToPowerOfTwo<Uint64>();
221+
}
222+
223+
template <typename T>
224+
void TestAlignDownToPowerOfTwo()
225+
{
226+
EXPECT_EQ(AlignDownToPowerOfTwo(T{0}), T{0});
227+
EXPECT_EQ(AlignDownToPowerOfTwo(T{1}), T{1});
228+
EXPECT_EQ(AlignDownToPowerOfTwo(T{2}), T{2});
229+
230+
for (T i = 2; i < sizeof(T) * 8 - 1; ++i)
231+
{
232+
T Pw2 = T{1} << i;
233+
T Pw2_1 = Pw2 >> T{1};
234+
T Test1 = Pw2 - T{1};
235+
T Test2 = Pw2_1 + T{1};
236+
EXPECT_EQ(AlignDownToPowerOfTwo(Pw2), Pw2);
237+
EXPECT_EQ(AlignDownToPowerOfTwo(Test1), Pw2_1);
238+
EXPECT_EQ(AlignDownToPowerOfTwo(Test2), Pw2_1);
239+
}
240+
}
241+
242+
TEST(Common_Align, AlignDownToPowerOfTwo)
243+
{
244+
TestAlignDownToPowerOfTwo<Uint8>();
245+
TestAlignDownToPowerOfTwo<Uint16>();
246+
TestAlignDownToPowerOfTwo<Uint32>();
247+
TestAlignDownToPowerOfTwo<Uint64>();
248+
}
249+
197250
} // namespace

0 commit comments

Comments
 (0)