From bdfb5dff0a74dbd110c6bc54dbe041ba48c0c356 Mon Sep 17 00:00:00 2001 From: floyd Date: Sun, 2 Feb 2025 01:04:45 +0100 Subject: [PATCH] gitbak --- power_gray.h | 54 ---------- src/search/binary.h | 256 ++++++++++++++++++++++++++++++++++++++++++++ src/search/convex.h | 107 ++++++++++++++++++ 3 files changed, 363 insertions(+), 54 deletions(-) delete mode 100644 power_gray.h create mode 100644 src/search/convex.h diff --git a/power_gray.h b/power_gray.h deleted file mode 100644 index 2d7224dc..00000000 --- a/power_gray.h +++ /dev/null @@ -1,54 +0,0 @@ -#pragma once - -#include - -template -class PowerGray { - constexpr static uint32_t BITS = sizeof(T) * 8u; - - // Return (gray_code**e)(x) - // gray_pow(x, 1) == gray_code(x) - // gray_pow(x, BITS_PER_LONG-1) == inverse_gray_code(x) - constexpr static inline T gray_pow(T x, T e) noexcept { - e &= (BITS-1); // modulo BITS_PER_LONG - T s = 1; - while ( e ) - { - if ( e & 1 ) x ^= x >> s; // gray ** s - s <<= 1; - e >>= 1; - } - return x; - } - - // Return (inverse_gray_code**(e))(x) - // == (gray_code**(-e))(x) - // inverse_gray_pow(x, 1) == inverse_gray_code(x) - // inverse_gray_pow(x, BITS_PER_LONG-1) == gray_code(x) - constexpr static inline T inverse_gray_pow(T x, T e) { - return gray_pow(x, -e); - } - - // Return (rev_gray_code**e)(x) - // rev_gray_pow(x, 1) == rev_gray_code(x) - // rev_gray_pow(x, BITS_PER_LONG-1) == inverse_rev_gray_code(x) - constexpr static inline T rev_gray_pow(T x, T e) { - e &= (BITS-1); // modulo BITS_PER_LONG - T s = 1; - while ( e ) - { - if ( e & 1 ) x ^= x << s; // rev_gray ** s - s <<= 1; - e >>= 1; - } - return x; - } - - // Return (inverse_rev_gray_code**(e))(x) - // == (rev_gray_code**(-e))(x) - // inverse_rev_gray_pow(x, 1) == inverse_rev_gray_code(x) - // inverse_rev_gray_pow(x, BITS_PER_LONG-1) == rev_gray_code(x) - constexpr static inline T inverse_rev_gray_pow(T x, T e) { - return rev_gray_pow(x, -e); - } -}; diff --git a/src/search/binary.h b/src/search/binary.h index 9d91564c..e19224d5 100644 --- a/src/search/binary.h +++ b/src/search/binary.h @@ -1,6 +1,7 @@ #ifndef CRYPTANALYSISLIB_SEARCH_BINARY_SEARCH_H #define CRYPTANALYSISLIB_SEARCH_BINARY_SEARCH_H +#include #ifndef CRYPTANALYSISLIB_SEARCH_H #error "do not include this file directly. Use `#inluce `" #endif @@ -16,6 +17,261 @@ #include "hash/hash.h" #include "math/math.h" +/// Source: https://www.jjj.de/fxt/fxtpage.html#fxtbook +/// Return index of first element in f[] that equals v +/// Return n if there is no such element. +/// f[] must be sorted in ascending order. +/// Must have n!=0 +template +size_t bsearch(const Type *f, + const size_t n, + const Type v) noexcept { + assert(n); + size_t nlo=0, nhi=n-1; + while ( nlo != nhi ) { + size_t t = (nhi+nlo)/2; + + if ( f[t] < v ) nlo = t + 1; + else nhi = t; + } + + if ( f[nhi]==v ) return nhi; + else return n; +} + +/// Return index of first element in f[] that is >= v +/// Return n if there is no such element. +/// f[] must be sorted in ascending order. +/// Must have n!=0 +template +size_t bsearch_geq(const Type *f, + const size_t n, + const Type v) { + assert(n); + size_t nlo=0, nhi=n-1; + while ( nlo != nhi ) { + size_t t = (nhi+nlo)/2; + + if ( f[t] < v ) nlo = t + 1; + else nhi = t; + } + + if ( f[nhi]>=v ) return nhi; + else return n; +} + +/// Return index of first element in f[] that is <= v +/// Return n (word with all bits set) if there is no such element. +/// f[] must be sorted in ascending order. +/// Must have n!=0 +template +size_t bsearch_leq(const Type *f, + const size_t n, + const Type v) noexcept { + assert(n); + size_t nlo=0, nhi=n-1; + while ( nlo != nhi ) { + size_t t = (nhi+nlo)/2; + + if ( f[t] > v ) nlo = t + 1; + else nhi = t; + } + + if ( f[nhi]<=v ) return nhi; + else return n; +} + +/// return index of first element in f[] that is == v +/// return n if there is no such element +/// f[] must be sorted in ascending order +/// must have n!=0 +template +size_t bsearch(const Type *f, + const size_t n, + const Type v, + int (*cmp)(const Type &, const Type &)) { + assert(n); + size_t nlo=0, nhi=n-1; + while ( nlo != nhi ) { + size_t t = (nhi+nlo)/2; + if ( cmp(f[t], v) < 0 ) nlo = t + 1; + else nhi = t; + } + + if ( cmp(f[nhi], v)==0 ) return nhi; + else return n; +} + +/// return index of first element in f[] that is >= v +/// return n if there is no such element +/// f[] must be sorted in ascending order +/// must have n!=0 +template +size_t bsearch_geq(const Type *f, + const size_t n, + const Type v, + int (*cmp)(const Type &, const Type &)) { + assert(n); + size_t nlo=0, nhi=n-1; + while ( nlo != nhi ) { + size_t t = (nhi+nlo)/2; + if ( cmp(f[t], v) < 0 ) nlo = t + 1; + else nhi = t; + } + + if ( cmp(f[nhi], v) >= 0 ) return nhi; + else return n; +} + +/// return index of first element in f[] that is <= v +/// return n if there is no such element +/// f[] must be sorted in ascending order +/// must have n!=0 +template +size_t bsearch_leq(const Type *f, + const ulong n, + const Type v, + int (*cmp)(const Type &, const Type &)) noexcept { + assert(n); + size_t nlo=0, nhi=n-1; + while ( nlo != nhi ) { + size_t t = (nhi+nlo)/2; + if ( cmp(f[t], v) > 0 ) nlo = t + 1; + else nhi = t; + } + + if ( cmp(f[nhi], v) <= 0 ) return nhi; + else return n; +} + +/// Return index of first element x in f[] for which |(x-v)| <= da +/// Return n if there is no such element. +/// f[] must be sorted in ascending order. +/// da must be positive. +/// +/// Makes sense only with inexact types (float or double). +/// Must have n!=0 +template +ulong bsearch_approx(const Type *f, + const ulong n, + const Type v, + const Type da) noexcept { + assert(n); + size_t k = bsearch_geq(f, n, v-da); + if (k +size_t bsearch_approx(const Type *f, + const size_t n, + const Type v, + const Type da, + int (*cmp)(const Type &, const Type &)) noexcept { + assert(n); + size_t k = bsearch_geq(f, n, v-da, cmp); + if ( k +size_t idx_bsearch(const Type *f, + const size_t n, + const size_t *x, + const Type v) noexcept { + ulong nlo=0, nhi=n-1; + while ( nlo != nhi ) { + ulong t = (nhi+nlo)/2; + + if ( f[x[t]] < v ) nlo = t + 1; + else nhi = t; + } + + if ( f[x[nhi]]==v ) return nhi; + else return n; +} + +/// Return minimal i so that f[x[i]] >= v. +/// Return n if there is no such i. +/// f[x[]] must be (index-)sorted in ascending order: +/// f[x[i]] <= f[x[i+i]] +/// Must have n!=0 +template +size_t idx_bsearch_geq(const Type *f, + const size_t n, + const ulong *x, + const Type v) noexcept { + size_t nlo=0, nhi=n-1; + while ( nlo != nhi ) { + size_t t = (nhi+nlo)/2; + + if ( f[x[t]] < v ) nlo = t + 1; + else nhi = t; + } + + if ( f[x[nhi]]>=v ) return nhi; + else return n; +} + +/// Return index-ptr i of first element in f[] that is == v +/// i.e. f[x[i]] == v, with i minimal. +/// Return n if there is no such element +/// f[x[]] must be (index-)sorted in ascending order: +/// f[x[i]] <= f[x[i+i]] +/// Must have n!=0 +template +size_t idx_bsearch(const Type *f, + const size_t n, + const ulong *x, + const Type v, + int (*cmp)(const Type &, const Type &)) { + size_t nlo=0, nhi=n-1; + while ( nlo != nhi ) { + size_t t = (nhi+nlo)/2; + if ( cmp(f[x[t]], v) < 0 ) nlo = t + 1; + else nhi = t; + } + + if ( cmp(f[x[nhi]], v)==0 ) return nhi; + else return n; +} + +/// Return index-ptr of first element in f[] that is >= v +/// i.e. f[x[i]] >= v, with i minimal. +/// Return n if there is no such element +/// f[x[]] must be (index-)sorted in ascending order: +/// f[x[i]] <= f[x[i+i]] +/// Must have n!=0 +template +size_t idx_bsearch_geq(const Type *f, + const size_t n, + const ulong *x, + const Type v, + int (*cmp)(const Type &, const Type &)) { + ulong nlo=0, nhi=n-1; + while (nlo != nhi) { + ulong t = (nhi+nlo)/2; + if ( cmp(f[x[t]], v)<0 ) nlo = t + 1; + else nhi = t; + } + + if ( cmp(f[x[nhi]], v)>=0 ) return nhi; + else return n; +} + /// See Paul Khuong's /// https://www.pvk.ca/Blog/2012/07/03/binary-search-star-eliminates-star-branch-mispredictions/ /// NOTE: probably wrong diff --git a/src/search/convex.h b/src/search/convex.h new file mode 100644 index 00000000..13f208ea --- /dev/null +++ b/src/search/convex.h @@ -0,0 +1,107 @@ + +template +ulong test_strictly_convex(const Type *f, ulong n) +// Return index of maximum for strictly convex sequence, +// otherwise return 0. +// "strictly convex" means "strongly unimodal" and there +// is at least one upstep and downstep in the sequence. +{ + if ( n<=2 ) return 0; + + // the following two lines make sure the searches below stop: + if ( f[0] >= f[1] ) return 0; + if ( f[n-2] <= f[n-1] ) return 0; + + ulong i = 0; + do { ++i; } while ( f[i-1] < f[i] ); + --i; + // i is second index of last rising pair from start + + ulong j = n - 1; + do { --j; } while ( f[j] > f[j+1] ); + ++j; + // j is first index of last falling pair from end (going backwards) + + if ( i!=j ) return 0; + return i; +} +// ------------------------- + + +template +ulong test_strictly_concave(const Type *f, ulong n) +// Return index of minimum for strictly concave sequence, +// otherwise return 0 +{ + if ( n<=2 ) return 0; + + // the following two lines make sure the searches below stop: + if ( f[0] <= f[1] ) return 0; + if ( f[n-2] >= f[n-1] ) return 0; + + ulong i = 0; + do { ++i; } while ( f[i-1] > f[i] ); + --i; + // i is second index of last falling pair from start + + ulong j = n - 1; + do { --j; } while ( f[j] < f[j+1] ); + ++j; + // j is first index of last rising pair from end (going backwards) + + if ( i!=j ) return 0; + return i; +} +// ------------------------- + +template +bool is_strictly_convex(const Type *f, ulong n) +{ return (0 != test_strictly_convex(f, n)); } + +template +bool is_strictly_concave(const Type *f, ulong n) +{ return (0 != test_strictly_concave(f, n)); } + + +template +bool is_weakly_convex(const Type *f, ulong n) +// Return whether sequence is weakly convex (weakly unimodal). +{ + if ( n<=2 ) return true; + ulong j = 1; + while ( j < n ) // scan over weakly increasing part + { + if ( f[j-1] > f[j] ) break; + ++j; + } + ++j; + while ( j < n ) // scan over weakly decreasing part + { + if ( f[j-1] < f[j] ) break; + ++j; + } + return ( j >= n ); +} +// ------------------------- + + + +template +bool is_weakly_concave(const Type *f, ulong n) +// Return whether sequence is weakly concave. +{ + if ( n<=2 ) return true; + ulong j = 1; + while ( j < n ) // scan over weakly decreasing part + { + if ( f[j-1] < f[j] ) break; + ++j; + } + ++j; + while ( j < n ) // scan over weakly increasing part + { + if ( f[j-1] > f[j] ) break; + ++j; + } + return ( j >= n ); +}