1
|
|
/*
|
2
|
|
*******************************************************************************
|
3
|
|
\file u16.c
|
4
|
|
\brief 16-bit unsigned words
|
5
|
|
\project bee2 [cryptographic library]
|
6
|
|
\author (C) Sergey Agievich [agievich@{bsu.by|gmail.com}]
|
7
|
|
\created 2015.10.28
|
8
|
|
\version 2019.07.08
|
9
|
|
\license This program is released under the GNU General Public License
|
10
|
|
version 3. See Copyright Notices in bee2/info.h.
|
11
|
|
*******************************************************************************
|
12
|
|
*/
|
13
|
|
|
14
|
|
#include "bee2/core/mem.h"
|
15
|
|
#include "bee2/core/u16.h"
|
16
|
|
#include "bee2/core/util.h"
|
17
|
|
|
18
|
|
/*
|
19
|
|
*******************************************************************************
|
20
|
|
Операции
|
21
|
|
|
22
|
|
Реализованные алгоритмы прокомментированы в u32.c.
|
23
|
|
*******************************************************************************
|
24
|
|
*/
|
25
|
|
|
26
|
1
|
u16 u16Rev(u16 w)
|
27
|
|
{
|
28
|
1
|
return w << 8 | w >> 8;
|
29
|
|
}
|
30
|
|
|
31
|
1
|
void u16Rev2(u16 buf[], size_t count)
|
32
|
|
{
|
33
|
1
|
ASSERT(memIsValid(buf, count * 2));
|
34
|
1
|
while (count--)
|
35
|
1
|
buf[count] = u16Rev(buf[count]);
|
36
|
|
}
|
37
|
|
|
38
|
1
|
size_t u16Weight(register u16 w)
|
39
|
|
{
|
40
|
1
|
w -= ((w >> 1) & 0x5555);
|
41
|
1
|
w = (w & 0x3333) + ((w >> 2) & 0x3333);
|
42
|
1
|
w = (w + (w >> 4)) & 0x0F0F;
|
43
|
1
|
w += w >> 8;
|
44
|
1
|
return (size_t)(w & 0x001F);
|
45
|
|
}
|
46
|
|
|
47
|
1
|
bool_t u16Parity(register u16 w)
|
48
|
|
{
|
49
|
1
|
w ^= w >> 1;
|
50
|
1
|
w ^= w >> 2;
|
51
|
1
|
w ^= w >> 4;
|
52
|
1
|
w ^= w >> 8;
|
53
|
1
|
return (bool_t)(w & U16_1);
|
54
|
|
}
|
55
|
|
|
56
|
1
|
size_t SAFE(u16CTZ)(register u16 w)
|
57
|
|
{
|
58
|
1
|
return 16 - u16Weight(w | (U16_0 - w));
|
59
|
|
}
|
60
|
|
|
61
|
1
|
size_t FAST(u16CTZ)(register u16 w)
|
62
|
|
{
|
63
|
1
|
register size_t l = 16;
|
64
|
|
register u16 t;
|
65
|
1
|
if (t = w << 8)
|
66
|
1
|
l -= 8, w = t;
|
67
|
1
|
if (t = w << 4)
|
68
|
1
|
l -= 4, w = t;
|
69
|
1
|
if (t = w << 2)
|
70
|
1
|
l -= 2, w = t;
|
71
|
1
|
t = 0;
|
72
|
1
|
return ((u16)(w << 1)) ? l - 2 : l - (w ? 1 : 0);
|
73
|
|
}
|
74
|
|
|
75
|
1
|
size_t SAFE(u16CLZ)(register u16 w)
|
76
|
|
{
|
77
|
1
|
w = w | w >> 1;
|
78
|
1
|
w = w | w >> 2;
|
79
|
1
|
w = w | w >> 4;
|
80
|
1
|
w = w | w >> 8;
|
81
|
1
|
return u16Weight(~w);
|
82
|
|
}
|
83
|
|
|
84
|
1
|
size_t FAST(u16CLZ)(register u16 w)
|
85
|
|
{
|
86
|
1
|
register size_t l = 16;
|
87
|
|
register u16 t;
|
88
|
1
|
if (t = w >> 8)
|
89
|
1
|
l -= 8, w = t;
|
90
|
1
|
if (t = w >> 4)
|
91
|
1
|
l -= 4, w = t;
|
92
|
1
|
if (t = w >> 2)
|
93
|
1
|
l -= 2, w = t;
|
94
|
1
|
t = 0;
|
95
|
1
|
return (w >> 1) ? l - 2 : l - (w ? 1 : 0);
|
96
|
|
}
|
97
|
|
|
98
|
1
|
u16 u16Shuffle(register u16 w)
|
99
|
|
{
|
100
|
|
register u16 t;
|
101
|
1
|
t = (w ^ (w >> 4)) & 0x00F0, w ^= t ^ (t << 4);
|
102
|
1
|
t = (w ^ (w >> 2)) & 0x0C0C, w ^= t ^ (t << 2);
|
103
|
1
|
t = (w ^ (w >> 1)) & 0x2222, w ^= t ^ (t << 1);
|
104
|
1
|
t = 0;
|
105
|
1
|
return w;
|
106
|
|
}
|
107
|
|
|
108
|
1
|
u16 u16Deshuffle(register u16 w)
|
109
|
|
{
|
110
|
|
register u16 t;
|
111
|
1
|
t = (w ^ (w >> 1)) & 0x2222, w ^= t ^ (t << 1);
|
112
|
1
|
t = (w ^ (w >> 2)) & 0x0C0C, w ^= t ^ (t << 2);
|
113
|
1
|
t = (w ^ (w >> 4)) & 0x00F0, w ^= t ^ (t << 4);
|
114
|
1
|
t = 0;
|
115
|
1
|
return w;
|
116
|
|
}
|
117
|
|
|
118
|
1
|
u16 u16NegInv(register u16 w)
|
119
|
|
{
|
120
|
1
|
register u16 ret = w;
|
121
|
1
|
ASSERT(w & 1);
|
122
|
1
|
ret = ret * (w * ret + 2);
|
123
|
1
|
ret = ret * (w * ret + 2);
|
124
|
1
|
ret = ret * (w * ret + 2);
|
125
|
1
|
ret = ret * (w * ret + 2);
|
126
|
1
|
w = 0;
|
127
|
1
|
return ret;
|
128
|
|
}
|
129
|
|
|
130
|
1
|
void u16From(u16 dest[], const void* src, size_t count)
|
131
|
|
{
|
132
|
1
|
ASSERT(memIsValid(src, count));
|
133
|
1
|
ASSERT(memIsValid(dest, count + count % 2));
|
134
|
1
|
memMove(dest, src, count);
|
135
|
1
|
if (count % 2)
|
136
|
1
|
((octet*)dest)[count] = 0;
|
137
|
|
#if (OCTET_ORDER == BIG_ENDIAN)
|
138
|
|
for (count = (count + 1) / 2; count--;)
|
139
|
|
dest[count] = u16Rev(dest[count]);
|
140
|
|
#endif // OCTET_ORDER
|
141
|
|
}
|
142
|
|
|
143
|
1
|
void u16To(void* dest, size_t count, const u16 src[])
|
144
|
|
{
|
145
|
1
|
ASSERT(memIsValid(src, count + count % 2));
|
146
|
1
|
ASSERT(memIsValid(dest, count));
|
147
|
1
|
memMove(dest, src, count);
|
148
|
|
#if (OCTET_ORDER == BIG_ENDIAN)
|
149
|
|
if (count % 2)
|
150
|
|
{
|
151
|
|
register u16 u = src[--count / 2];
|
152
|
|
((octet*)dest)[count] = (octet)u;
|
153
|
|
u = 0;
|
154
|
|
}
|
155
|
|
for (count /= 2; count--;)
|
156
|
|
((u16*)dest)[count] = u16Rev(((u16*)dest)[count]);
|
157
|
|
#endif // OCTET_ORDER
|
158
|
|
}
|