A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
hash-fnv.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2012 Lawrence Livermore National Laboratory
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation;
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16 *
17 * Author: Peter D. Barnes, Jr. <pdbarnes@llnl.gov>
18 *
19 * This copyright notice applies strictly to the wrapper material.
20 *
21 * The FNV source code itself is in the public domain. The FNV source
22 * code sections are marked by
23 * // Begin <fnv-file> ---->
24 * and
25 * // End <fnv-file> ---->
26 * comments.
27 *
28 * Code changes from the FNV distribution are marked with `//PDB'
29 * In addition comment blocks have been converted to Doxygen format.
30 */
31
32#include "hash-fnv.h"
33
34#include "log.h"
35
36#include <stdlib.h>
37#include <sys/types.h>
38
39/**
40 * \file
41 * \ingroup hash
42 * \brief ns3::Hash::Function::Fnv1a implementation.
43 */
44
45namespace ns3
46{
47
48NS_LOG_COMPONENT_DEFINE("Hash-Fnv");
49
50namespace Hash
51{
52
53namespace Function
54{
55
56/** FNV hash implementation details. */
57namespace Fnv1aImplementation
58{
59
60/*************************************************
61 ** class FnvHashImplementation
62 ************************************************/
63
64/**
65 * \ingroup hash
66 * \defgroup hash_fnv FNV Hash Implementation
67 */
68/**@{*/
69
70extern "C"
71{
72 // NOLINTBEGIN
73 // clang-format off
74
75// Changes from FNV distribution are marked with `//PDB'
76//
77
78/* Begin fnv.h ----------------------------------------> */
79
80/*
81 * fnv - Fowler/Noll/Vo- hash code
82 *
83 * @(#) $Revision: 5.4 $
84 * @(#) $Id: fnv.h,v 5.4 2009/07/30 22:49:13 chongo Exp $
85 * @(#) $Source: /usr/local/src/cmd/fnv/RCS/fnv.h,v $
86 *
87 ***
88 *
89 * Fowler/Noll/Vo- hash
90 *
91 * The basis of this hash algorithm was taken from an idea sent
92 * as reviewer comments to the IEEE POSIX P1003.2 committee by:
93 *
94 * Phong Vo (http://www.research.att.com/info/kpv/)
95 * Glenn Fowler (http://www.research.att.com/~gsf/)
96 *
97 * In a subsequent ballot round:
98 *
99 * Landon Curt Noll (http://www.isthe.com/chongo/)
100 *
101 * improved on their algorithm. Some people tried this hash
102 * and found that it worked rather well. In an EMail message
103 * to Landon, they named it the ``Fowler/Noll/Vo'' or FNV hash.
104 *
105 * FNV hashes are designed to be fast while maintaining a low
106 * collision rate. The FNV speed allows one to quickly hash lots
107 * of data while maintaining a reasonable collision rate. See:
108 *
109 * http://www.isthe.com/chongo/tech/comp/fnv/index.html
110 *
111 * for more details as well as other forms of the FNV hash.
112 *
113 ***
114 *
115 * NOTE: The FNV-0 historic hash is not recommended. One should use
116 * the FNV-1 hash instead.
117 *
118 * To use the 32 bit FNV-0 historic hash, pass FNV0_32_INIT as the
119 * Fnv32_t hashval argument to fnv_32_buf() or fnv_32_str().
120 *
121 * To use the 64 bit FNV-0 historic hash, pass FNV0_64_INIT as the
122 * Fnv64_t hashval argument to fnv_64_buf() or fnv_64_str().
123 *
124 * To use the recommended 32 bit FNV-1 hash, pass FNV1_32_INIT as the
125 * Fnv32_t hashval argument to fnv_32_buf() or fnv_32_str().
126 *
127 * To use the recommended 64 bit FNV-1 hash, pass FNV1_64_INIT as the
128 * Fnv64_t hashval argument to fnv_64_buf() or fnv_64_str().
129 *
130 * To use the recommended 32 bit FNV-1a hash, pass FNV1_32A_INIT as the
131 * Fnv32_t hashval argument to fnv_32a_buf() or fnv_32a_str().
132 *
133 * To use the recommended 64 bit FNV-1a hash, pass FNV1A_64_INIT as the
134 * Fnv64_t hashval argument to fnv_64a_buf() or fnv_64a_str().
135 *
136 ***
137 *
138 * Please do not copyright this code. This code is in the public domain.
139 *
140 * LANDON CURT NOLL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
141 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
142 * EVENT SHALL LANDON CURT NOLL BE LIABLE FOR ANY SPECIAL, INDIRECT OR
143 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
144 * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
145 * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
146 * PERFORMANCE OF THIS SOFTWARE.
147 *
148 * By:
149 * chongo <Landon Curt Noll> /\oo/\
150 * http://www.isthe.com/chongo/
151 *
152 * Share and Enjoy! :-)
153 */
154
155#if !defined(__FNV_H__)
156/** Include guard from the original fnv.h. */
157#define __FNV_H__
158
159
160//#include <sys/types.h> //PDB
161
162#define FNV_VERSION "5.0.2" /**< @(#) FNV Version */
163
164
165/**
166 * 32 bit FNV-0 hash type
167 */
168typedef uint32_t Fnv32_t; //PDB
169
170
171/**
172 * 32 bit FNV-0 zero initial basis
173 *
174 * This historic hash is not recommended. One should use
175 * the FNV-1 hash and initial basis instead.
176 */
177// Use fully qualified type so this define works outside this scope //PDB
178#define FNV0_32_INIT ((Fnv1aImplementation::Fnv32_t)0)
179
180
181/**
182 * 32 bit FNV-1 and FNV-1a non-zero initial basis
183 *
184 * The FNV-1 initial basis is the FNV-0 hash of the following 32 octets:
185 *
186 * chongo <Landon Curt Noll> /\../\
187 *
188 * \note The \'s above are not back-slashing escape characters.
189 * They are literal ASCII backslash 0x5c characters.
190 *
191 * \note The FNV-1a initial basis is the same value as FNV-1 by definition.
192 */
193// Use fully qualified type so this define works outside this scope //PDB
194#define FNV1_32_INIT ((Fnv1aImplementation::Fnv32_t)0x811c9dc5)
195/** \copydoc FNV1_32_INIT */
196#define FNV1_32A_INIT FNV1_32_INIT
197
198
199/**
200 * Determine how 64 bit unsigned values are represented
201 */
202//#include "longlong.h" //PDB - assume `unsigned long long' is 64 bit
203#define HAVE_64BIT_LONG_LONG
204
205
206
207/**
208 * 64 bit FNV-0 hash
209 */
210#if defined(HAVE_64BIT_LONG_LONG)
211typedef uint64_t Fnv64_t; //PDB
212#else /* HAVE_64BIT_LONG_LONG */
213typedef struct {
214 uint32_t w32[2]; /* w32[0] is low order, w32[1] is high order word */ //PDB
215} Fnv64_t;
216#endif /* HAVE_64BIT_LONG_LONG */
217
218
219/**
220 * 64 bit FNV-0 zero initial basis
221 *
222 * This historic hash is not recommended. One should use
223 * the FNV-1 hash and initial basis instead.
224 */
225// Use fully qualified type so this define works outside this scope //PDB
226#if defined(HAVE_64BIT_LONG_LONG)
227#define FNV0_64_INIT ((Fnv1aImplementation::Fnv64_t)0)
228#else /* HAVE_64BIT_LONG_LONG */
229extern const Fnv64_t fnv0_64_init;
230#define FNV0_64_INIT (Fnv1aImplementation::fnv0_64_init)
231#endif /* HAVE_64BIT_LONG_LONG */
232
233
234/**
235 * 64 bit FNV-1 non-zero initial basis
236 *
237 * The FNV-1 initial basis is the FNV-0 hash of the following 32 octets:
238 *
239 * chongo <Landon Curt Noll> /\../\
240 *
241 * \note The \'s above are not back-slashing escape characters.
242 * They are literal ASCII backslash 0x5c characters.
243 *
244 * \note The FNV-1a initial basis is the same value as FNV-1 by definition.
245 */
246#if defined(HAVE_64BIT_LONG_LONG)
247#define FNV1_64_INIT ((Fnv1aImplementation::Fnv64_t)0xcbf29ce484222325ULL)
248/** \copydoc FNV1_64_INIT */
249#define FNV1A_64_INIT FNV1_64_INIT
250#else /* HAVE_64BIT_LONG_LONG */
251extern const fnv1_64_init;
252extern const Fnv64_t fnv1a_64_init;
253#define FNV1_64_INIT (fnv1_64_init)
254/** \copydoc FNV1_64_INIT */
255#define FNV1A_64_INIT (fnv1a_64_init)
256#endif /* HAVE_64BIT_LONG_LONG */
257
258
259/**
260 * FNV hash types
261 */
263 FNV_NONE = 0, /**< invalid FNV hash type */
264 FNV0_32 = 1, /**< FNV-0 32 bit hash */
265 FNV1_32 = 2, /**< FNV-1 32 bit hash */
266 FNV1a_32 = 3, /**< FNV-1a 32 bit hash */
267 FNV0_64 = 4, /**< FNV-0 64 bit hash */
268 FNV1_64 = 5, /**< FNV-1 64 bit hash */
269 FNV1a_64 = 6, /**< FNV-1a 64 bit hash */
270};
271
272//PDB test vector declarations deleted
273
274/*
275 * external functions //PDB converted to forward declarations
276 */
277/** \copydoc fnv_32a_buf() */
278/* extern */ Fnv32_t fnv_32_buf(void *buf, size_t len, Fnv32_t hval);
279/** \copydoc fnv_32a_str() */
280/* extern */ Fnv32_t fnv_32_str(char *str, Fnv32_t hval);
281
282/* hash_32a.c */
283/* extern */ Fnv32_t fnv_32a_buf(void *buf, size_t len, Fnv32_t hashval);
284/* extern */ Fnv32_t fnv_32a_str(char *buf, Fnv32_t hashval);
285
286/* hash_64.c */
287/** \copydoc fnv_64a_buf() */
288/* extern */ Fnv64_t fnv_64_buf(void *buf, size_t len, Fnv64_t hval);
289/** \copydoc fnv_64a_str() */
290/* extern */ Fnv64_t fnv_64_str(char *str, Fnv64_t hval);
291
292/* hash_64a.c */
293/* extern */ Fnv64_t fnv_64a_buf(void *buf, size_t len, Fnv64_t hashval);
294/* extern */ Fnv64_t fnv_64a_str(char *buf, Fnv64_t hashval);
295
296//PDB test vector declarations deleted
297
298
299#endif /* __FNV_H__ */
300
301/* End fnv.h ------------------------------------------> */
302
303/* Begin hash_32a.c -----------------------------------> */
304
305/*
306 * hash_32 - 32 bit Fowler/Noll/Vo FNV-1a hash code
307 *
308 * @(#) $Revision: 5.1 $
309 * @(#) $Id: hash_32a.c,v 5.1 2009/06/30 09:13:32 chongo Exp $
310 * @(#) $Source: /usr/local/src/cmd/fnv/RCS/hash_32a.c,v $
311 *
312 ***
313 *
314 * Fowler/Noll/Vo hash
315 *
316 * The basis of this hash algorithm was taken from an idea sent
317 * as reviewer comments to the IEEE POSIX P1003.2 committee by:
318 *
319 * Phong Vo (http://www.research.att.com/info/kpv/)
320 * Glenn Fowler (http://www.research.att.com/~gsf/)
321 *
322 * In a subsequent ballot round:
323 *
324 * Landon Curt Noll (http://www.isthe.com/chongo/)
325 *
326 * improved on their algorithm. Some people tried this hash
327 * and found that it worked rather well. In an EMail message
328 * to Landon, they named it the ``Fowler/Noll/Vo'' or FNV hash.
329 *
330 * FNV hashes are designed to be fast while maintaining a low
331 * collision rate. The FNV speed allows one to quickly hash lots
332 * of data while maintaining a reasonable collision rate. See:
333 *
334 * http://www.isthe.com/chongo/tech/comp/fnv/index.html
335 *
336 * for more details as well as other forms of the FNV hash.
337 ***
338 *
339 * To use the recommended 32 bit FNV-1a hash, pass FNV1_32A_INIT as the
340 * Fnv32_t hashval argument to fnv_32a_buf() or fnv_32a_str().
341 *
342 ***
343 *
344 * Please do not copyright this code. This code is in the public domain.
345 *
346 * LANDON CURT NOLL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
347 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
348 * EVENT SHALL LANDON CURT NOLL BE LIABLE FOR ANY SPECIAL, INDIRECT OR
349 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
350 * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
351 * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
352 * PERFORMANCE OF THIS SOFTWARE.
353 *
354 * By:
355 * chongo <Landon Curt Noll> /\oo/\
356 * http://www.isthe.com/chongo/
357 *
358 * Share and Enjoy! :-)
359 */
360
361//#include <stdlib.h> //PDB
362//#include "fnv.h" //PDB
363
364
365/**
366 * 32 bit magic FNV-1a prime
367 */
368#define FNV_32_PRIME ((Fnv1aImplementation::Fnv32_t)0x01000193)
369
370
371/**
372 * fnv_32a_buf - perform a 32 bit Fowler/Noll/Vo FNV-1a hash on a buffer
373 *
374 * input:
375 * \param [in] buf start of buffer to hash
376 * \param [in] len length of buffer in octets
377 * \param [in] hval previous hash value or 0 if first call
378 *
379 * \returns 32 bit hash as a static hash type.
380 *
381 * \note To use the recommended 32 bit FNV-1a hash, use FNV1_32A_INIT as the
382 * hval arg on the first call to either fnv_32a_buf() or fnv_32a_str().
383 */
385fnv_32a_buf(void *buf, size_t len, Fnv32_t hval)
386{
387 unsigned char *bp = (unsigned char *)buf; /* start of buffer */
388 unsigned char *be = bp + len; /* beyond end of buffer */
389
390 /*
391 * FNV-1a hash each octet in the buffer
392 */
393 while (bp < be) {
394
395 /* xor the bottom with the current octet */
396 hval ^= (Fnv32_t)*bp++;
397
398 /* multiply by the 32 bit FNV magic prime mod 2^32 */
399#if defined(NO_FNV_GCC_OPTIMIZATION)
400 hval *= FNV_32_PRIME;
401#else
402 hval += (hval<<1) + (hval<<4) + (hval<<7) + (hval<<8) + (hval<<24);
403#endif
404 }
405
406 /* return our new hash value */
407 return hval;
408}
409
410
411/**
412 * fnv_32a_str - perform a 32 bit Fowler/Noll/Vo FNV-1a hash on a string
413 *
414 * input:
415 * \param [in] str string to hash
416 * \param [in] hval previous hash value or 0 if first call
417 *
418 * \returns 32 bit hash as a static hash type
419 *
420 * \note To use the recommended 32 bit FNV-1a hash, use FNV1_32A_INIT as the
421 * hval arg on the first call to either fnv_32a_buf() or fnv_32a_str().
422 */
424fnv_32a_str(char *str, Fnv32_t hval)
425{
426 unsigned char *s = (unsigned char *)str; /* unsigned string */
427
428 /*
429 * FNV-1a hash each octet in the buffer
430 */
431 while (*s) {
432
433 /* xor the bottom with the current octet */
434 hval ^= (Fnv32_t)*s++;
435
436 /* multiply by the 32 bit FNV magic prime mod 2^32 */
437#if defined(NO_FNV_GCC_OPTIMIZATION)
438 hval *= FNV_32_PRIME;
439#else
440 hval += (hval<<1) + (hval<<4) + (hval<<7) + (hval<<8) + (hval<<24);
441#endif
442 }
443
444 /* return our new hash value */
445 return hval;
446}
447
448/* End hash_32a.c -------------------------------------> */
449
450/* Begin hash_64a.c -----------------------------------> */
451
452/*
453 * hash_64 - 64 bit Fowler/Noll/Vo-0 FNV-1a hash code
454 *
455 * @(#) $Revision: 5.1 $
456 * @(#) $Id: hash_64a.c,v 5.1 2009/06/30 09:01:38 chongo Exp $
457 * @(#) $Source: /usr/local/src/cmd/fnv/RCS/hash_64a.c,v $
458 *
459 ***
460 *
461 * Fowler/Noll/Vo hash
462 *
463 * The basis of this hash algorithm was taken from an idea sent
464 * as reviewer comments to the IEEE POSIX P1003.2 committee by:
465 *
466 * Phong Vo (http://www.research.att.com/info/kpv/)
467 * Glenn Fowler (http://www.research.att.com/~gsf/)
468 *
469 * In a subsequent ballot round:
470 *
471 * Landon Curt Noll (http://www.isthe.com/chongo/)
472 *
473 * improved on their algorithm. Some people tried this hash
474 * and found that it worked rather well. In an EMail message
475 * to Landon, they named it the ``Fowler/Noll/Vo'' or FNV hash.
476 *
477 * FNV hashes are designed to be fast while maintaining a low
478 * collision rate. The FNV speed allows one to quickly hash lots
479 * of data while maintaining a reasonable collision rate. See:
480 *
481 * http://www.isthe.com/chongo/tech/comp/fnv/index.html
482 *
483 * for more details as well as other forms of the FNV hash.
484 *
485 ***
486 *
487 * To use the recommended 64 bit FNV-1a hash, pass FNV1A_64_INIT as the
488 * Fnv64_t hashval argument to fnv_64a_buf() or fnv_64a_str().
489 *
490 ***
491 *
492 * Please do not copyright this code. This code is in the public domain.
493 *
494 * LANDON CURT NOLL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
495 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
496 * EVENT SHALL LANDON CURT NOLL BE LIABLE FOR ANY SPECIAL, INDIRECT OR
497 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
498 * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
499 * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
500 * PERFORMANCE OF THIS SOFTWARE.
501 *
502 * By:
503 * chongo <Landon Curt Noll> /\oo/\
504 * http://www.isthe.com/chongo/
505 *
506 * Share and Enjoy! :-)
507 */
508
509//#include <stdlib.h> //PDB
510//#include "fnv.h" //PDB
511
512
513/**
514 * FNV-1a defines the initial basis to be non-zero
515 */
516#if !defined(HAVE_64BIT_LONG_LONG)
517const Fnv64_t fnv1a_64_init = { 0x84222325, 0xcbf29ce4 };
518#endif /* ! HAVE_64BIT_LONG_LONG */
519
520
521/**
522 * 64 bit magic FNV-1a prime
523 */
524/**@{*/
525#if defined(HAVE_64BIT_LONG_LONG)
526#define FNV_64_PRIME ((Fnv1aImplementation::Fnv64_t)0x100000001b3ULL)
527#else /* HAVE_64BIT_LONG_LONG */
528#define FNV_64_PRIME_LOW ((unsigned long)0x1b3) /* lower bits of FNV prime */
529#define FNV_64_PRIME_SHIFT (8) /* top FNV prime shift above 2^32 */
530#endif /* HAVE_64BIT_LONG_LONG */
531/**@}*/
532
533
534/**
535 * fnv_64a_buf - perform a 64 bit Fowler/Noll/Vo FNV-1a hash on a buffer
536 *
537 * input:
538 * \param [in] buf start of buffer to hash
539 * \param [in] len length of buffer in octets
540 * \param [in] hval previous hash value or 0 if first call
541 *
542 * \returns 64 bit hash as a static hash type
543 *
544 * \note To use the recommended 64 bit FNV-1a hash, use FNV1A_64_INIT as the
545 * hval arg on the first call to either fnv_64a_buf() or fnv_64a_str().
546 */
548fnv_64a_buf(void *buf, size_t len, Fnv64_t hval)
549{
550 unsigned char *bp = (unsigned char *)buf; /* start of buffer */
551 unsigned char *be = bp + len; /* beyond end of buffer */
552
553#if defined(HAVE_64BIT_LONG_LONG)
554 /*
555 * FNV-1a hash each octet of the buffer
556 */
557 while (bp < be) {
558
559 /* xor the bottom with the current octet */
560 hval ^= (Fnv64_t)*bp++;
561
562 /* multiply by the 64 bit FNV magic prime mod 2^64 */
563#if defined(NO_FNV_GCC_OPTIMIZATION)
564 hval *= FNV_64_PRIME;
565#else /* NO_FNV_GCC_OPTIMIZATION */
566 hval += (hval << 1) + (hval << 4) + (hval << 5) +
567 (hval << 7) + (hval << 8) + (hval << 40);
568#endif /* NO_FNV_GCC_OPTIMIZATION */
569 }
570
571#else /* HAVE_64BIT_LONG_LONG */
572
573 unsigned long val[4]; /* hash value in base 2^16 */
574 unsigned long tmp[4]; /* tmp 64 bit value */
575
576 /*
577 * Convert Fnv64_t hval into a base 2^16 array
578 */
579 val[0] = hval.w32[0];
580 val[1] = (val[0] >> 16);
581 val[0] &= 0xffff;
582 val[2] = hval.w32[1];
583 val[3] = (val[2] >> 16);
584 val[2] &= 0xffff;
585
586 /*
587 * FNV-1a hash each octet of the buffer
588 */
589 while (bp < be) {
590
591 /* xor the bottom with the current octet */
592 val[0] ^= (unsigned long)*bp++;
593
594 /*
595 * multiply by the 64 bit FNV magic prime mod 2^64
596 *
597 * Using 0x100000001b3 we have the following digits base 2^16:
598 *
599 * 0x0 0x100 0x0 0x1b3
600 *
601 * which is the same as:
602 *
603 * 0x0 1<<FNV_64_PRIME_SHIFT 0x0 FNV_64_PRIME_LOW
604 */
605 /* multiply by the lowest order digit base 2^16 */
606 tmp[0] = val[0] * FNV_64_PRIME_LOW;
607 tmp[1] = val[1] * FNV_64_PRIME_LOW;
608 tmp[2] = val[2] * FNV_64_PRIME_LOW;
609 tmp[3] = val[3] * FNV_64_PRIME_LOW;
610 /* multiply by the other non-zero digit */
611 tmp[2] += val[0] << FNV_64_PRIME_SHIFT; /* tmp[2] += val[0] * 0x100 */
612 tmp[3] += val[1] << FNV_64_PRIME_SHIFT; /* tmp[3] += val[1] * 0x100 */
613 /* propagate carries */
614 tmp[1] += (tmp[0] >> 16);
615 val[0] = tmp[0] & 0xffff;
616 tmp[2] += (tmp[1] >> 16);
617 val[1] = tmp[1] & 0xffff;
618 val[3] = tmp[3] + (tmp[2] >> 16);
619 val[2] = tmp[2] & 0xffff;
620 /*
621 * Doing a val[3] &= 0xffff; is not really needed since it simply
622 * removes multiples of 2^64. We can discard these excess bits
623 * outside of the loop when we convert to Fnv64_t.
624 */
625 }
626
627 /*
628 * Convert base 2^16 array back into an Fnv64_t
629 */
630 hval.w32[1] = ((val[3]<<16) | val[2]);
631 hval.w32[0] = ((val[1]<<16) | val[0]);
632
633#endif /* HAVE_64BIT_LONG_LONG */
634
635 /* return our new hash value */
636 return hval;
637}
638
639
640/**
641 * fnv_64a_str - perform a 64 bit Fowler/Noll/Vo FNV-1a hash on a buffer
642 *
643 * input:
644 * \param [in] str string to hash
645 * \param [in] hval previous hash value or 0 if first call
646 *
647 * \returns 64 bit hash as a static hash type
648 *
649 * \note To use the recommended 64 bit FNV-1a hash, use FNV1A_64_INIT as the
650 * hval arg on the first call to either fnv_64a_buf() or fnv_64a_str().
651 */
653fnv_64a_str(char *str, Fnv64_t hval)
654{
655 unsigned char *s = (unsigned char *)str; /* unsigned string */
656
657#if defined(HAVE_64BIT_LONG_LONG)
658
659 /*
660 * FNV-1a hash each octet of the string
661 */
662 while (*s) {
663
664 /* xor the bottom with the current octet */
665 hval ^= (Fnv64_t)*s++;
666
667 /* multiply by the 64 bit FNV magic prime mod 2^64 */
668#if defined(NO_FNV_GCC_OPTIMIZATION)
669 hval *= FNV_64_PRIME;
670#else /* NO_FNV_GCC_OPTIMIZATION */
671 hval += (hval << 1) + (hval << 4) + (hval << 5) +
672 (hval << 7) + (hval << 8) + (hval << 40);
673#endif /* NO_FNV_GCC_OPTIMIZATION */
674 }
675
676#else /* !HAVE_64BIT_LONG_LONG */
677
678 unsigned long val[4]; /* hash value in base 2^16 */
679 unsigned long tmp[4]; /* tmp 64 bit value */
680
681 /*
682 * Convert Fnv64_t hval into a base 2^16 array
683 */
684 val[0] = hval.w32[0];
685 val[1] = (val[0] >> 16);
686 val[0] &= 0xffff;
687 val[2] = hval.w32[1];
688 val[3] = (val[2] >> 16);
689 val[2] &= 0xffff;
690
691 /*
692 * FNV-1a hash each octet of the string
693 */
694 while (*s) {
695
696 /* xor the bottom with the current octet */
697
698 /*
699 * multiply by the 64 bit FNV magic prime mod 2^64
700 *
701 * Using 1099511628211, we have the following digits base 2^16:
702 *
703 * 0x0 0x100 0x0 0x1b3
704 *
705 * which is the same as:
706 *
707 * 0x0 1<<FNV_64_PRIME_SHIFT 0x0 FNV_64_PRIME_LOW
708 */
709 /* multiply by the lowest order digit base 2^16 */
710 tmp[0] = val[0] * FNV_64_PRIME_LOW;
711 tmp[1] = val[1] * FNV_64_PRIME_LOW;
712 tmp[2] = val[2] * FNV_64_PRIME_LOW;
713 tmp[3] = val[3] * FNV_64_PRIME_LOW;
714 /* multiply by the other non-zero digit */
715 tmp[2] += val[0] << FNV_64_PRIME_SHIFT; /* tmp[2] += val[0] * 0x100 */
716 tmp[3] += val[1] << FNV_64_PRIME_SHIFT; /* tmp[3] += val[1] * 0x100 */
717 /* propagate carries */
718 tmp[1] += (tmp[0] >> 16);
719 val[0] = tmp[0] & 0xffff;
720 tmp[2] += (tmp[1] >> 16);
721 val[1] = tmp[1] & 0xffff;
722 val[3] = tmp[3] + (tmp[2] >> 16);
723 val[2] = tmp[2] & 0xffff;
724 /*
725 * Doing a val[3] &= 0xffff; is not really needed since it simply
726 * removes multiples of 2^64. We can discard these excess bits
727 * outside of the loop when we convert to Fnv64_t.
728 */
729 val[0] ^= (unsigned long)(*s++);
730 }
731
732 /*
733 * Convert base 2^16 array back into an Fnv64_t
734 */
735 hval.w32[1] = ((val[3]<<16) | val[2]);
736 hval.w32[0] = ((val[1]<<16) | val[0]);
737
738#endif /* !HAVE_64BIT_LONG_LONG */
739
740 /* return our new hash value */
741 return hval;
742}
743
744/* End hash_64a.c -------------------------------------> */
745
746 // clang-format on
747 // NOLINTEND
748
749} /* extern "C" */
750
751//-----------------------------------------------------------------------------
752
753/**@}*/ // \defgroup hash_fnv
754
755} // namespace Fnv1aImplementation
756
758{
759 clear();
760}
761
763Fnv1a::GetHash32(const char* buffer, const std::size_t size)
764{
765 m_hash32 = Fnv1aImplementation::fnv_32a_buf((void*)buffer, size, m_hash32);
766 return m_hash32;
767}
768
769uint64_t
770Fnv1a::GetHash64(const char* buffer, const std::size_t size)
771{
772 m_hash64 = Fnv1aImplementation::fnv_64a_buf((void*)buffer, size, m_hash64);
773 return m_hash64;
774}
775
776void
778{
781}
782
783} // namespace Function
784
785} // namespace Hash
786
787} // namespace ns3
uint32_t m_hash32
Cache last hash value, for incremental hashing.
Definition: hash-fnv.h:105
uint32_t GetHash32(const char *buffer, const size_t size) override
Compute 32-bit hash of a byte buffer.
Definition: hash-fnv.cc:763
uint64_t GetHash64(const char *buffer, const size_t size) override
Compute 64-bit hash of a byte buffer.
Definition: hash-fnv.cc:770
uint64_t m_hash64
Cache last hash value, for incremental hashing.
Definition: hash-fnv.h:106
void clear() override
Restore initial state.
Definition: hash-fnv.cc:777
uint64_t Fnv64_t
64 bit FNV-0 hash
Definition: hash-fnv.cc:211
#define FNV1A_64_INIT
64 bit FNV-1 non-zero initial basis
Definition: hash-fnv.cc:249
#define FNV1_32A_INIT
32 bit FNV-1 and FNV-1a non-zero initial basis
Definition: hash-fnv.cc:196
Fnv32_t fnv_32_str(char *str, Fnv32_t hval)
fnv_32a_str - perform a 32 bit Fowler/Noll/Vo FNV-1a hash on a string
Fnv64_t fnv_64_str(char *str, Fnv64_t hval)
fnv_64a_str - perform a 64 bit Fowler/Noll/Vo FNV-1a hash on a buffer
Fnv32_t fnv_32a_str(char *buf, Fnv32_t hashval)
fnv_32a_str - perform a 32 bit Fowler/Noll/Vo FNV-1a hash on a string
Definition: hash-fnv.cc:424
#define FNV_64_PRIME
FNV-1a defines the initial basis to be non-zero.
Definition: hash-fnv.cc:526
uint32_t Fnv32_t
32 bit FNV-0 hash type
Definition: hash-fnv.cc:168
Fnv64_t fnv_64_buf(void *buf, size_t len, Fnv64_t hval)
fnv_64a_buf - perform a 64 bit Fowler/Noll/Vo FNV-1a hash on a buffer
Fnv64_t fnv_64a_str(char *buf, Fnv64_t hashval)
fnv_64a_str - perform a 64 bit Fowler/Noll/Vo FNV-1a hash on a buffer
Definition: hash-fnv.cc:653
Fnv32_t fnv_32_buf(void *buf, size_t len, Fnv32_t hval)
fnv_32a_buf - perform a 32 bit Fowler/Noll/Vo FNV-1a hash on a buffer
#define FNV_32_PRIME
32 bit magic FNV-1a prime
Definition: hash-fnv.cc:368
Fnv32_t fnv_32a_buf(void *buf, size_t len, Fnv32_t hashval)
fnv_32a_buf - perform a 32 bit Fowler/Noll/Vo FNV-1a hash on a buffer
Definition: hash-fnv.cc:385
Fnv64_t fnv_64a_buf(void *buf, size_t len, Fnv64_t hashval)
fnv_64a_buf - perform a 64 bit Fowler/Noll/Vo FNV-1a hash on a buffer
Definition: hash-fnv.cc:548
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:202
ns3::Hash::Function::Fnv1a declaration.
Debug message logging.
Every class exported by the ns3 library is enclosed in the ns3 namespace.