File: keyHash.m

package info (click to toggle)
octave-datatypes 1.1.8-2
  • links: PTS, VCS
  • area: main
  • in suites: forky
  • size: 3,228 kB
  • sloc: cpp: 24,903; xml: 509; objc: 269; ansic: 23; makefile: 17
file content (95 lines) | stat: -rw-r--r-- 3,358 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
## Copyright (C) 2025-2026 Andreas Bertsatos <abertsatos@biol.uoa.gr>
##
## This file is part of the datatypes package for GNU Octave.
##
## This program is free software; you can redistribute it and/or modify it under
## the terms of the GNU General Public License as published by the Free Software
## Foundation; either version 3 of the License, or (at your option) any later
## version.
##
## This program is distributed in the hope that it will be useful, but WITHOUT
## ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
## FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
## details.
##
## You should have received a copy of the GNU General Public License along with
## this program; if not, see <http://www.gnu.org/licenses/>.

## -*- texinfo -*-
## @deftypefn  {datatypes} {@var{hey} =} keyHash (@var{X})
## @deftypefnx {datatypes} {@var{hey} =} keyHash (@var{X}, @var{base})
##
## Generate a hash code for an array.
##
## @code{@var{h} = keyHash (@var{X})} generates a @qcode{uint64} scalar that
## represents the input @var{X}, which may be numeric, logical, or character
## array or cell array of character vectors.  @code{keyHash} utilizes the 64-bit
## FMV-1a variant of the Fowler-Noll-Vo non-cryptographic hash function.
##
## @code{@var{h} = keyHash (@var{X}), @var{base}} also generates a 64-bit
## hash code using @var{base} as the offset basis for the FNV-1a hash
## algorithm.  @var{base} must be a @qcode{uint64} integer type scalar.  Use
## this syntax to cascade @code{keyHash} on multiple objects for which a
## single hash code is required.
##
## Note that unlike MATLAB, this implementation does no use any random seed.
## As a result, @code{keyHash} will always generate the exact same hash key
## for any particular input across different workers and Octave sessions.
##
## @end deftypefn
function key = keyHash (x = [], base = [])
  ## Validate input
  if (isempty (x))
    error ("keyHash: X cannot not be empty.");
  endif
  ## Initialize string with size and class name
  size_str = sprintf ('%dx', size (x))(1:end-1);
  init_str = [size_str class(x)];
  if (base)
    if (! (isscalar (base) && isa (base, 'uint64')))
      error ("keyHash: BASE must be a UINT64 scalar.");
    endif
    key = __ckeyHash__(init_str, base);
  else
    key = __ckeyHash__(init_str);
  endif
  ## Select data type
  if (isnumeric (x) || islogical (x))
    key = __nkeyHash__(x(:), key);
  elseif (ischar (x))
    key = __ckeyHash__(x(:), key);
  elseif (iscellstr (x))
    key = __ckeyHash__([x{:}], key);
  else
    error ("keyHash: unsupported input type.");
  endif
endfunction

%!test
%! key = keyHash (1);
%! assert (isscalar (key), true);
%! key = keyHash ([1:5]);
%! assert (isscalar (key), true);
%!test
%! key1 = keyHash (1);
%! key2 = keyHash (1, 0xcbf29ce484222325); # default offset basis
%! assert (key1, key2);
%!test
%! key1 = keyHash (0);
%! assert (class (key1), 'uint64');
%!test
%! A = [1:5];
%! B = [1:5];
%! key1 = keyHash (A);
%! key2 = keyHash (B);
%! assert (key1, key2);
%!test
%! A = [1:5];
%! B = [1:5]';
%! key1 = keyHash (A);
%! key2 = keyHash (B);
%! assert (isequal (key1, key2), false);

%!error<keyHash: X cannot not be empty.> keyHash ();
%!error<keyHash: BASE must be a UINT64 scalar.> keyHash (1, 1);
%!error<keyHash: unsupported input type.> keyHash (@(x) x);