Skip to content

Instantly share code, notes, and snippets.

@gfody
Last active July 12, 2022 22:44
Show Gist options
  • Save gfody/d6b0a917a7ce88fc0fe736ab31e08e37 to your computer and use it in GitHub Desktop.
Save gfody/d6b0a917a7ce88fc0fe736ab31e08e37 to your computer and use it in GitHub Desktop.
create function imul(@a bigint, @b bigint) returns table as return
with
_0 as (select a = convert(binary(8), @a), b = convert(binary(8), @b)),
_1 as (select
hi_a = convert(bigint, substring(a, 1, 4)), lo_a = @a & 0xFFFFFFFF,
hi_b = convert(bigint, substring(b, 1, 4)), lo_b = @b & 0xFFFFFFFF from _0),
_2 as (select *, x = convert(binary(8), lo_a * lo_b) from _1),
_3 as (select s0 = substring(x, 5, 4), x = convert(bigint, substring(x, 1, 4)), hi_a, hi_b, lo_a, lo_b from _2),
_4 as (select x = (hi_a * lo_b + x) & 0xFFFFFFFF, s0, hi_b, lo_a from _3)
select value = convert(bigint, convert(binary(4), x + lo_a * hi_b) + s0) from _4
create function fnv64(@s nvarchar(max)) returns table as return
with r(i, h) as (
select 1, convert(bigint, -3750763034362895579)
union all
select i + 1, m.value from r
cross apply imul(r.h ^ unicode(substring(@s, i, 1)), 1099511628211) m
where i <= len(@s))
select top 1 value = h from r order by i desc
select s, expected, actual = value from (values
('test1', 2271358237066212092),
('', -3750763034362895579),
(N'オーバーフロー', 5848856640766145455))
x(s, expected) cross apply fnv64(s)
option (maxrecursion 0)
@gfody
Copy link
Author

gfody commented May 25, 2022

challenge: implement FNV-1a in t-sql. there are no unsigned ints and overflows are not allowed, good luck!
output must match this reference function:

long fnv64(string s)
{
    var h = 14695981039346656037UL;
    for (int i = 0; i < s.Length; i++)
        h = (h ^ s[i]) * 1099511628211UL;
    return (long)h;
}

bonus: make it inlineable

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment