├── LICENSE.md ├── conf ├── Unix.mk └── Win.mk ├── TODO.md ├── mk ├── NMake.mk ├── SingleUnix.mk ├── Defaults.mk ├── Rules.mk └── mkrules.sh ├── src ├── mul.c ├── config.h ├── inner.h ├── oram1.c ├── hex.c ├── base64.c └── int31.c ├── Makefile ├── README.md └── test └── testcttk.c /LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright (c) 2018 Thomas Pornin `` 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining 4 | a copy of this software and associated documentation files (the 5 | "Software"), to deal in the Software without restriction, including 6 | without limitation the rights to use, copy, modify, merge, publish, 7 | distribute, sublicense, and/or sell copies of the Software, and to 8 | permit persons to whom the Software is furnished to do so, subject to 9 | the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be 12 | included in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 18 | BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 19 | ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /conf/Unix.mk: -------------------------------------------------------------------------------- 1 | # Configuration for a native build on a generic Unix-like system. 2 | 3 | # Build directory. 4 | BUILD = build 5 | 6 | # Extension for executable files. 7 | E = 8 | 9 | # Extension for object files. 10 | O = .o 11 | 12 | # Prefix for library file name. 13 | LP = lib 14 | 15 | # Extension for library file name. 16 | L = .a 17 | 18 | # Prefix for DLL file name. 19 | DP = lib 20 | 21 | # Extension for DLL file name. 22 | D = .so 23 | 24 | # Output file names can be overridden directly. By default, they are 25 | # assembled using the prefix/extension macros defined above. 26 | # CTTKLIB = libcttk.a 27 | # CTTKDLL = libcttk.so 28 | # TESTCTTK = testcttk 29 | 30 | # File deletion tool. 31 | RM = rm -f 32 | 33 | # Directory creation tool. 34 | MKDIR = mkdir -p 35 | 36 | # C compiler and flags. 37 | CC = cc 38 | CFLAGS = -W -Wall -O2 -fPIC 39 | CCOUT = -c -o 40 | 41 | # Static library building tool. 42 | AR = ar 43 | ARFLAGS = -rcs 44 | AROUT = 45 | 46 | # DLL building tool. 47 | LDDLL = cc 48 | LDDLLFLAGS = -shared 49 | LDDLLOUT = -o 50 | 51 | # Static linker. 52 | LD = cc 53 | LDFLAGS = 54 | LDOUT = -o 55 | 56 | # Set the values to 'no' to disable building of the corresponding element 57 | # by default. Building can still be invoked with an explicit target call 58 | # (e.g. 'make dll' to force build the DLL). 59 | #STATICLIB = no 60 | #DLL = no 61 | #TESTS = no 62 | -------------------------------------------------------------------------------- /TODO.md: -------------------------------------------------------------------------------- 1 | Here is a mostly unordered list of stuff that should be done with 2 | CTTK: 3 | 4 | - Big integers: division with unsigned interpretation. 5 | - Big integers: multiplication optimisation with Karatsuba. 6 | - Big integers: division optimisation (word-wise processing). 7 | - Big integers: conversions to and from strings (binary, decimal, 8 | hexadecimal). 9 | - Big integers: extra implementation with 15-bit words (i15). 10 | - Big integers: extra implementation with 63-bit words (i63). 11 | - Modular integers (with odd modulus, possibly prime). 12 | - SIMD optimisations (SSE2, AVX2...). 13 | - Oblivious RAM with sub-linear cost. 14 | - Storage and search structures (maps). 15 | - Automatic bitslicing metaprogramming tool. 16 | 17 | The following features have been implemented: 18 | 19 | - Boolean type and operations. 20 | - Comparisons of 32-bit and 64-bit integers. 21 | - Constant-time conditional copy and swap of buffers. 22 | - Constant-time buffer comparisons (equality, lexicographic order). 23 | - Constant-time array lookup (with O(N) cost). 24 | - Hexadecimal encoder / decoder. 25 | - Base64 encoder / decoder. 26 | - Big integers: base definitions and conversions to/from native 27 | integers. 28 | - Big integers: extending and narrowing conversions. 29 | - Big integers: addition and subtraction. 30 | - Big integers: multiplication. 31 | - Big integers: Euclidean division. 32 | - Big integers: left and right shifts. 33 | - Big integers: boolean bitwise operations. 34 | -------------------------------------------------------------------------------- /conf/Win.mk: -------------------------------------------------------------------------------- 1 | # Configuration for a native build on a Windows system with Visual Studio. 2 | 3 | # Build directory. 4 | BUILD = build 5 | 6 | # Extension for executable files. 7 | E = .exe 8 | 9 | # Extension for object files. 10 | O = .obj 11 | 12 | # Prefix for static library file name. 13 | LP = 14 | 15 | # Extension for static library file name. We add an 's' so that the 16 | # name is distinct from the 'import library' generated along with the DLL. 17 | L = s.lib 18 | 19 | # Prefix for DLL file name. 20 | DP = 21 | 22 | # Extension for DLL file name. 23 | D = .dll 24 | 25 | # Output file names can be overridden directly. By default, they are 26 | # assembled using the prefix/extension macros defined above. 27 | # CTTKLIB = cttks.lib 28 | # CTTKDLL = cttk.dll 29 | # TESTCTTK = testcttk.exe 30 | 31 | # File deletion tool. 32 | RM = del /Q 33 | 34 | # Directory creation tool. 35 | MKDIR = mkdir 36 | 37 | # C compiler and flags. 38 | CC = cl 39 | CFLAGS = -nologo -W2 -O2 40 | CCOUT = -c -Fo 41 | 42 | # Static library building tool. 43 | AR = lib 44 | ARFLAGS = -nologo 45 | AROUT = -out: 46 | 47 | # DLL building tool. 48 | LDDLL = cl 49 | LDDLLFLAGS = -nologo -LD -MT 50 | LDDLLOUT = -Fe 51 | 52 | # Static linker. 53 | LD = cl 54 | LDFLAGS = -nologo 55 | LDOUT = -Fe 56 | 57 | # Set the values to 'no' to disable building of the corresponding element 58 | # by default. Building can still be invoked with an explicit target call 59 | # (e.g. 'make dll' to force build the DLL). 60 | #STATICLIB = no 61 | #DLL = no 62 | #TOOLS = no 63 | #TESTS = no 64 | -------------------------------------------------------------------------------- /mk/NMake.mk: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2017 Thomas Pornin 2 | # 3 | # Permission is hereby granted, free of charge, to any person obtaining 4 | # a copy of this software and associated documentation files (the 5 | # "Software"), to deal in the Software without restriction, including 6 | # without limitation the rights to use, copy, modify, merge, publish, 7 | # distribute, sublicense, and/or sell copies of the Software, and to 8 | # permit persons to whom the Software is furnished to do so, subject to 9 | # the following conditions: 10 | # 11 | # The above copyright notice and this permission notice shall be 12 | # included in all copies or substantial portions of the Software. 13 | # 14 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17 | # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 18 | # BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 19 | # ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | # SOFTWARE. 22 | 23 | # ====================================================================== 24 | 25 | # This file sets variables for use with NMake.exe, as distributed with 26 | # Visual Studio. 27 | 28 | # Load generic defaults. 29 | !include mk/Defaults.mk 30 | 31 | # Default configuration is 'Win' (native build with Visual Studio). 32 | CONF = Win 33 | 34 | # Path separator. 35 | P = ^\ 36 | 37 | !include conf/$(CONF).mk 38 | !include mk/Rules.mk 39 | -------------------------------------------------------------------------------- /mk/SingleUnix.mk: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2018 Thomas Pornin 2 | # 3 | # Permission is hereby granted, free of charge, to any person obtaining 4 | # a copy of this software and associated documentation files (the 5 | # "Software"), to deal in the Software without restriction, including 6 | # without limitation the rights to use, copy, modify, merge, publish, 7 | # distribute, sublicense, and/or sell copies of the Software, and to 8 | # permit persons to whom the Software is furnished to do so, subject to 9 | # the following conditions: 10 | # 11 | # The above copyright notice and this permission notice shall be 12 | # included in all copies or substantial portions of the Software. 13 | # 14 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17 | # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 18 | # BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 19 | # ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | # SOFTWARE. 22 | 23 | # ====================================================================== 24 | 25 | # This file sets variables for use with a SingleUnix-compatible 'make' 26 | # utility. 27 | 28 | # Load generic default. 29 | include mk/Defaults.mk 30 | 31 | # Path separator. 32 | P = / 33 | 34 | # Default configuration is 'Unix' (native build on a Unix-like system). 35 | CONF = Unix 36 | 37 | include conf/$(CONF).mk 38 | include mk/Rules.mk 39 | -------------------------------------------------------------------------------- /mk/Defaults.mk: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2018 Thomas Pornin 2 | # 3 | # Permission is hereby granted, free of charge, to any person obtaining 4 | # a copy of this software and associated documentation files (the 5 | # "Software"), to deal in the Software without restriction, including 6 | # without limitation the rights to use, copy, modify, merge, publish, 7 | # distribute, sublicense, and/or sell copies of the Software, and to 8 | # permit persons to whom the Software is furnished to do so, subject to 9 | # the following conditions: 10 | # 11 | # The above copyright notice and this permission notice shall be 12 | # included in all copies or substantial portions of the Software. 13 | # 14 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17 | # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 18 | # BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 19 | # ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | # SOFTWARE. 22 | 23 | # ====================================================================== 24 | 25 | # This file sets variables with generic default values, which can be 26 | # overridden in the selected configuration file. 27 | 28 | BUILD = build 29 | OBJDIR = $(BUILD)$Pobj 30 | CTTKLIB = $(BUILD)$P$(LP)cttk$L 31 | CTTKDLL = $(BUILD)$P$(DP)cttk$D 32 | TESTCTTK = $(BUILD)$Ptestcttk$E 33 | INCFLAGS = -Isrc -Iinc 34 | STATICLIB = lib 35 | DLL = dll 36 | TESTS = tests 37 | -------------------------------------------------------------------------------- /mk/Rules.mk: -------------------------------------------------------------------------------- 1 | # Automatically generated rules. Use 'mkrules.sh' to modify/regenerate. 2 | 3 | OBJ = \ 4 | $(OBJDIR)$Pbase64$O \ 5 | $(OBJDIR)$Phex$O \ 6 | $(OBJDIR)$Pint31$O \ 7 | $(OBJDIR)$Pmul$O \ 8 | $(OBJDIR)$Poram1$O 9 | OBJTESTCTTK = \ 10 | $(OBJDIR)$Ptestcttk$O 11 | HEADERSPUB = inc$Pcttk.h 12 | HEADERSPRIV = $(HEADERSPUB) src$Pconfig.h src$Pinner.h 13 | 14 | all: $(STATICLIB) $(DLL) $(TESTS) 15 | 16 | no: 17 | 18 | lib: $(CTTKLIB) 19 | 20 | dll: $(CTTKDLL) 21 | 22 | tests: $(TESTCTTK) 23 | 24 | clean: 25 | -$(RM) $(OBJDIR)$P*$O 26 | -$(RM) $(CTTKLIB) $(CTTKDLL) $(TESTCTTK) 27 | 28 | $(OBJDIR): 29 | -$(MKDIR) $(OBJDIR) 30 | 31 | $(CTTKLIB): $(OBJDIR) $(OBJ) 32 | $(AR) $(ARFLAGS) $(AROUT)$(CTTKLIB) $(OBJ) 33 | 34 | $(CTTKDLL): $(OBJDIR) $(OBJ) 35 | $(LDDLL) $(LDDLLFLAGS) $(LDDLLOUT)$(CTTKDLL) $(OBJ) 36 | 37 | $(TESTCTTK): $(CTTKLIB) $(OBJTESTCTTK) 38 | $(LD) $(LDFLAGS) $(LDOUT)$(TESTCTTK) $(OBJTESTCTTK) $(CTTKLIB) 39 | 40 | $(OBJDIR)$Pbase64$O: src$Pbase64.c $(HEADERSPRIV) 41 | $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pbase64$O src$Pbase64.c 42 | 43 | $(OBJDIR)$Phex$O: src$Phex.c $(HEADERSPRIV) 44 | $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Phex$O src$Phex.c 45 | 46 | $(OBJDIR)$Pint31$O: src$Pint31.c $(HEADERSPRIV) 47 | $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pint31$O src$Pint31.c 48 | 49 | $(OBJDIR)$Pmul$O: src$Pmul.c $(HEADERSPRIV) 50 | $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pmul$O src$Pmul.c 51 | 52 | $(OBJDIR)$Poram1$O: src$Poram1.c $(HEADERSPRIV) 53 | $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Poram1$O src$Poram1.c 54 | 55 | $(OBJDIR)$Ptestcttk$O: test$Ptestcttk.c $(HEADERSPRIV) 56 | $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Ptestcttk$O test$Ptestcttk.c 57 | -------------------------------------------------------------------------------- /src/mul.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 Thomas Pornin 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining 5 | * a copy of this software and associated documentation files (the 6 | * "Software"), to deal in the Software without restriction, including 7 | * without limitation the rights to use, copy, modify, merge, publish, 8 | * distribute, sublicense, and/or sell copies of the Software, and to 9 | * permit persons to whom the Software is furnished to do so, subject to 10 | * the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be 13 | * included in all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 19 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 20 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | #include "inner.h" 26 | 27 | /* see cttk.h */ 28 | uint32_t 29 | cttk_mulu32(uint32_t x, uint32_t y) 30 | { 31 | return mulu32(x, y); 32 | } 33 | 34 | /* see cttk.h */ 35 | int32_t 36 | cttk_muls32(int32_t x, int32_t y) 37 | { 38 | return muls32(x, y); 39 | } 40 | 41 | /* see cttk.h */ 42 | uint64_t 43 | cttk_mulu32w(uint32_t x, uint32_t y) 44 | { 45 | return mulu32w(x, y); 46 | } 47 | 48 | /* see cttk.h */ 49 | int64_t 50 | cttk_muls32w(int32_t x, int32_t y) 51 | { 52 | return muls32w(x, y); 53 | } 54 | 55 | /* see cttk.h */ 56 | uint64_t 57 | cttk_mulu64(uint64_t x, uint64_t y) 58 | { 59 | return mulu64(x, y); 60 | } 61 | 62 | /* see cttk.h */ 63 | int64_t 64 | cttk_muls64(int64_t x, int64_t y) 65 | { 66 | return muls64(x, y); 67 | } 68 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2018 Thomas Pornin 2 | # 3 | # Permission is hereby granted, free of charge, to any person obtaining 4 | # a copy of this software and associated documentation files (the 5 | # "Software"), to deal in the Software without restriction, including 6 | # without limitation the rights to use, copy, modify, merge, publish, 7 | # distribute, sublicense, and/or sell copies of the Software, and to 8 | # permit persons to whom the Software is furnished to do so, subject to 9 | # the following conditions: 10 | # 11 | # The above copyright notice and this permission notice shall be 12 | # included in all copies or substantial portions of the Software. 13 | # 14 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17 | # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 18 | # BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 19 | # ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | # SOFTWARE. 22 | 23 | # ===================================================================== 24 | 25 | # The lines below are a horrible hack that nonetheless works. On a 26 | # "make" utility compatible with Single Unix v4 (this includes GNU and 27 | # BSD make), the '\' at the end of a command line counts as an escape 28 | # for the newline character, so the next line is still a comment. 29 | # However, Microsoft's nmake.exe (that comes with Visual Studio) does 30 | # not interpret the final '\' that way in a comment. The end result is 31 | # that when using nmake.exe, this will include "mk/NMake.mk", whereas 32 | # GNU/BSD make will include "mk/SingleUnix.mk". 33 | 34 | # \ 35 | !ifndef 0 # \ 36 | !include mk/NMake.mk # \ 37 | !else 38 | .POSIX: 39 | include mk/SingleUnix.mk 40 | # Extra hack for OpenBSD make. 41 | ifndef: all 42 | 0: all 43 | endif: all 44 | # \ 45 | !endif 46 | -------------------------------------------------------------------------------- /src/config.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 Thomas Pornin 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining 5 | * a copy of this software and associated documentation files (the 6 | * "Software"), to deal in the Software without restriction, including 7 | * without limitation the rights to use, copy, modify, merge, publish, 8 | * distribute, sublicense, and/or sell copies of the Software, and to 9 | * permit persons to whom the Software is furnished to do so, subject to 10 | * the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be 13 | * included in all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 19 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 20 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | #ifndef CONFIG_H__ 26 | #define CONFIG_H__ 27 | 28 | /* 29 | * This file contains compile-time flags and option that can override 30 | * the autodetection performed in relevant files. 31 | * 32 | * Most of these macros are "flags" which have three settings: 33 | * 34 | * - Enabled: value should be defined to 1. 35 | * - Disabled: value should be defined to 0. 36 | * - Autodetection: value should be undefined, allowing the default 37 | * behaviour to take place. 38 | */ 39 | 40 | /* 41 | * If CTTK_CTMUL is set, then this is equivalent to setting all 42 | * of the following flags to the same value: 43 | * CTTK_CTMUL32 44 | * CTTK_CTMULU32W 45 | * CTTK_CTMULS32W 46 | * CTTK_CTMUL64 47 | * These flags can still be set individually, and will then override 48 | * the CTTK_CTMUL value. 49 | */ 50 | 51 | /* 52 | * If CTTK_CTMUL32 is set, then the 32-bit multiplication opcode (with 53 | * 32-bit result) is assumed to be constant-time. 54 | * 55 | #define CTTK_CTMUL32 1 56 | */ 57 | 58 | /* 59 | * If CTTK_CTMULU32W is set, then the 32x32->64 unsigned multiplication 60 | * is assumed to be constant-time. 61 | * 62 | #define CTTK_CTMULU32W 1 63 | */ 64 | 65 | /* 66 | * If CTTK_CTMULS32W is set, then the 32x32->64 signed multiplication 67 | * is assumed to be constant-time. 68 | * 69 | #define CTTK_CTMULS32W 1 70 | */ 71 | 72 | /* 73 | * If CTTK_CTMUL64 is set, then the 64-bit multiplication opcode (with 74 | * 64-bit result) is assumed to be constant-time. 75 | * 76 | #define CTTK_CTMUL64 1 77 | */ 78 | 79 | /* 80 | * If CTTK_NO_MALLOC is set, then the header will not be 81 | * included, and no dynamic memory allocation will be performed. Dynamic 82 | * memory allocation is performed for some arithmetic operations that 83 | * require extra space, when operands exceed the size that can be handled 84 | * with only stack buffers (see CTTK_MAX_INT_BUF). 85 | * 86 | #define CTTK_NO_MALLOC 1 87 | */ 88 | 89 | /* 90 | * The CTTK_MAX_INT_BUF macro defines the maximum size, in bytes, of 91 | * temporary integers allocated on the stack as part of some arithmetic 92 | * operations. Functions that need several such temporaries will use 93 | * CTTK_MAX_INT_BUF as the total aggregate size of such temporaries. 94 | * If the required size is greater, then dynamic memory allocation is 95 | * used, unless it was disabled with CTTK_NO_MALLOC, in which case the 96 | * result will be forcibly set to NaN. 97 | * 98 | * Don't define this value to less than 64. Default is 4096. 99 | * 100 | #define CTTK_MAX_INT_BUF 4096 101 | */ 102 | 103 | #endif 104 | -------------------------------------------------------------------------------- /mk/mkrules.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | 3 | # ======================================================================== 4 | # 5 | # Copyright (c) 2018 Thomas Pornin 6 | # 7 | # Permission is hereby granted, free of charge, to any person obtaining 8 | # a copy of this software and associated documentation files (the 9 | # "Software"), to deal in the Software without restriction, including 10 | # without limitation the rights to use, copy, modify, merge, publish, 11 | # distribute, sublicense, and/or sell copies of the Software, and to 12 | # permit persons to whom the Software is furnished to do so, subject to 13 | # the following conditions: 14 | # 15 | # The above copyright notice and this permission notice shall be 16 | # included in all copies or substantial portions of the Software. 17 | # 18 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 19 | # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20 | # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 21 | # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 22 | # BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 23 | # ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 24 | # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 25 | # SOFTWARE. 26 | # 27 | # ======================================================================== 28 | # 29 | # This script is used to generate the 'Rules.mk' file from the list 30 | # of source file included below. If the list changes (e.g. to add a 31 | # new source file), then add it here and rerun this script. 32 | # 33 | # ======================================================================== 34 | 35 | # Solaris compatibility: switch to a more POSIX-compliant /bin/sh. 36 | if [ -z "$CT_SCRIPT_LOOP" ] ; then 37 | CT_SCRIPT_LOOP=yes 38 | export CT_SCRIPT_LOOP 39 | if [ -x /usr/xpg6/bin/sh ] ; then 40 | exec /usr/xpg6/bin/sh "$0" "$@" 41 | fi 42 | if [ -x /usr/xpg4/bin/sh ] ; then 43 | exec /usr/xpg4/bin/sh "$0" "$@" 44 | fi 45 | fi 46 | 47 | # Exit on first error. 48 | set -e 49 | 50 | # Source files. Please keep in alphabetical order. 51 | coresrc=" \ 52 | src/base64.c \ 53 | src/hex.c \ 54 | src/int31.c \ 55 | src/mul.c \ 56 | src/oram1.c" 57 | 58 | # Source files the the 'testcttk' command-line tool. 59 | testcttksrc=" \ 60 | test/testcttk.c" 61 | 62 | # Public header files. 63 | headerspub=" \ 64 | inc/cttk.h" 65 | 66 | # Private header files. 67 | headerspriv=" \ 68 | src/config.h \ 69 | src/inner.h" 70 | 71 | # Function to turn slashes into $P (macro for path separator). 72 | escsep() { 73 | printf '%s' "$1" | sed 's/\//$P/g' 74 | } 75 | 76 | # Create rules file. 77 | rm -f Rules.mk 78 | cat > Rules.mk <> Rules.mk 99 | 100 | cat >> Rules.mk <> Rules.mk 140 | -------------------------------------------------------------------------------- /src/inner.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 Thomas Pornin 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining 5 | * a copy of this software and associated documentation files (the 6 | * "Software"), to deal in the Software without restriction, including 7 | * without limitation the rights to use, copy, modify, merge, publish, 8 | * distribute, sublicense, and/or sell copies of the Software, and to 9 | * permit persons to whom the Software is furnished to do so, subject to 10 | * the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be 13 | * included in all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 19 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 20 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | #ifndef INNER_H__ 26 | #define INNER_H__ 27 | 28 | #include 29 | #include 30 | 31 | #include "config.h" 32 | #include "cttk.h" 33 | 34 | /* ==================================================================== */ 35 | 36 | #if !CTTK_NO_MALLOC 37 | #include 38 | #endif 39 | 40 | /* 41 | * We allow stack-based temporaries to use up to 4 kB of stack. With the i31 42 | * implementation, this is good for one integer up to 31713 bits. 43 | */ 44 | #if !defined CTTK_MAX_INT_BUF 45 | #define CTTK_MAX_INT_BUF 4096 46 | #endif 47 | 48 | #ifdef CTTK_CTMUL 49 | #ifndef CTTK_CTMUL32 50 | #define CTTK_CTMUL32 CTTK_CTMUL 51 | #endif 52 | #ifndef CTTK_CTMULU32W 53 | #define CTTK_CTMULU32W CTTK_CTMUL 54 | #endif 55 | #ifndef CTTK_CTMULS32W 56 | #define CTTK_CTMULS32W CTTK_CTMUL 57 | #endif 58 | #ifndef CTTK_CTMUL64 59 | #define CTTK_CTMUL64 CTTK_CTMUL 60 | #endif 61 | #endif 62 | 63 | /* ==================================================================== */ 64 | 65 | #if CTTK_CTMUL32 66 | #define mulu32(x, y) ((uint32_t)((uint32_t)(x) * (uint32_t)(y))) 67 | #else 68 | static inline uint32_t 69 | mulu32(uint32_t x, uint32_t y) 70 | { 71 | int i; 72 | uint32_t z; 73 | 74 | z = 0; 75 | for (i = 0; i < 32; i ++) { 76 | z += x & -(y & 1); 77 | x <<= 1; 78 | y >>= 1; 79 | } 80 | return z; 81 | } 82 | #endif 83 | 84 | static inline int32_t 85 | muls32(int32_t x, int32_t y) 86 | { 87 | uint32_t r; 88 | 89 | r = mulu32((uint32_t)x, (uint32_t)y); 90 | return *(int32_t *)&r; 91 | } 92 | 93 | #if CTTK_CTMULU32W 94 | #define mulu32w(x, y) ((uint64_t)((uint64_t)(uint32_t)(x) \ 95 | * (uint64_t)(uint32_t)(y))) 96 | #else 97 | static inline uint64_t 98 | mulu32w(uint32_t x, uint32_t y) 99 | { 100 | int i; 101 | uint64_t xe, z; 102 | 103 | z = 0; 104 | xe = x; 105 | for (i = 0; i < 32; i ++) { 106 | z += xe & -(uint64_t)(y & 1); 107 | xe <<= 1; 108 | y >>= 1; 109 | } 110 | return z; 111 | } 112 | #endif 113 | 114 | #if CTTK_CTMULS32W 115 | #define muls32w(x, y) ((int64_t)((int64_t)(int32_t)(x) \ 116 | * (int64_t)(int32_t)(y))) 117 | #else 118 | static inline int64_t 119 | muls32w(int32_t x, int32_t y) 120 | { 121 | uint32_t xu, yu, xh, yh; 122 | uint64_t z; 123 | 124 | xu = (uint32_t)x; 125 | yu = (uint32_t)y; 126 | xh = xu >> 31; 127 | yh = yu >> 31; 128 | xu &= 0x7FFFFFFF; 129 | yu &= 0x7FFFFFFF; 130 | z = mulu32w(xu, yu); 131 | z -= ((uint64_t)(xu & -yh) + (uint64_t)(yu & -xh)) << 31; 132 | z += (uint64_t)(xh & yh) << 62; 133 | return *(int64_t *)&z; 134 | } 135 | #endif 136 | 137 | #if CTTK_CTMUL64 138 | #define mulu64(x, y) ((uint64_t)((uint64_t)(x) * (uint64_t)(y))) 139 | #else 140 | static inline uint64_t 141 | mulu64(uint64_t x, uint64_t y) 142 | { 143 | uint64_t z; 144 | int i; 145 | 146 | z = 0; 147 | for (i = 0; i < 64; i ++) { 148 | z += x & -(y & 1); 149 | x <<= 1; 150 | y >>= 1; 151 | } 152 | return z; 153 | } 154 | #endif 155 | 156 | static inline int64_t 157 | muls64(int64_t x, int64_t y) 158 | { 159 | uint64_t r; 160 | 161 | r = mulu64((uint64_t)x, (uint64_t)y); 162 | return *(int64_t *)&r; 163 | } 164 | 165 | /* ==================================================================== */ 166 | 167 | #endif 168 | -------------------------------------------------------------------------------- /src/oram1.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 Thomas Pornin 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining 5 | * a copy of this software and associated documentation files (the 6 | * "Software"), to deal in the Software without restriction, including 7 | * without limitation the rights to use, copy, modify, merge, publish, 8 | * distribute, sublicense, and/or sell copies of the Software, and to 9 | * permit persons to whom the Software is furnished to do so, subject to 10 | * the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be 13 | * included in all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 19 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 20 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | #include "inner.h" 26 | 27 | /* see cttk.h */ 28 | void 29 | cttk_cond_copy(cttk_bool ctl, void *dst, const void *src, size_t len) 30 | { 31 | /* 32 | * TODO: make optimised versions for special cases: 33 | * 34 | * - We can copy by full words, depending on alignment (and 35 | * architecture tolerance for unaligned accesses), even in 36 | * case of overlap (it suffices to do the copy in the 37 | * appropriate direction). 38 | * 39 | * - We may use SSE2, AVX2, or similar vector operands on 40 | * platforms that support them. 41 | * 42 | * Code below is the basic, portable variant. It relies on the 43 | * idea that if source and destination overlap, then converting 44 | * the pointers to integers should preserve ordering. 45 | */ 46 | unsigned char *bdst; 47 | const unsigned char *bsrc; 48 | size_t u; 49 | 50 | /* 51 | * In order to perform a constant-time copy, we need to read the 52 | * current contents of the destination buffer, which may be, from 53 | * the point of view of the C compiler, uninitialised. Note that 54 | * reading uninitialised values of a character type is actually 55 | * supported by the C standard (values are unspecified, but this 56 | * shall incur no trap representation, and therefore no undefined 57 | * behaviour). 58 | */ 59 | bdst = dst; 60 | bsrc = src; 61 | if ((uintptr_t)dst <= (uintptr_t)src) { 62 | u = 0; 63 | while (u < len) { 64 | bdst[u] ^= (bsrc[u] ^ bdst[u]) & -ctl.v; 65 | u ++; 66 | } 67 | } else { 68 | u = len; 69 | while (u > 0) { 70 | u --; 71 | bdst[u] ^= (bsrc[u] ^ bdst[u]) & -ctl.v; 72 | } 73 | } 74 | } 75 | 76 | /* see cttk.h */ 77 | void 78 | cttk_cond_swap(cttk_bool ctl, void *a, void *b, size_t len) 79 | { 80 | /* 81 | * TODO: make optimised versions for special cases: 82 | * 83 | * - We can copy by full words, depending on alignment (and 84 | * architecture tolerance for unaligned accesses), even in 85 | * case of overlap (it suffices to do the copy in the 86 | * appropriate direction). 87 | * 88 | * - We may use SSE2, AVX2, or similar vector operands on 89 | * platforms that support them. 90 | * 91 | * Code below is the basic, portable variant. 92 | */ 93 | unsigned char *za, *zb; 94 | size_t u; 95 | 96 | za = a; 97 | zb = b; 98 | 99 | for (u = 0; u < len; u ++) { 100 | uint32_t x; 101 | 102 | x = (za[u] ^ zb[u]) & -ctl.v; 103 | za[u] ^= x; 104 | zb[u] ^= x; 105 | } 106 | } 107 | 108 | /* see cttk.h */ 109 | void 110 | cttk_array_read(void *d, 111 | const void *a, size_t elt_len, size_t num_len, size_t index) 112 | { 113 | size_t u; 114 | const unsigned char *b; 115 | 116 | memset(d, 0, elt_len); 117 | for (u = 0, b = a; u < num_len; u ++, b += elt_len) { 118 | cttk_cond_copy(cttk_u64_eq(u, index), d, b, elt_len); 119 | } 120 | } 121 | 122 | /* see cttk.h */ 123 | void 124 | cttk_array_write(void *a, size_t elt_len, size_t num_len, 125 | size_t index, const void *s) 126 | { 127 | size_t u; 128 | unsigned char *b; 129 | 130 | for (u = 0, b = a; u < num_len; u ++, b += elt_len) { 131 | cttk_cond_copy(cttk_u64_eq(u, index), b, s, elt_len); 132 | } 133 | } 134 | 135 | /* see cttk.h */ 136 | cttk_bool 137 | cttk_array_eq(const void *src1, const void *src2, size_t len) 138 | { 139 | const unsigned char *buf1, *buf2; 140 | size_t u; 141 | uint32_t r; 142 | 143 | r = 0; 144 | buf1 = src1; 145 | buf2 = src2; 146 | for (u = 0; u < len; u ++) { 147 | r |= buf1[u] ^ buf2[u]; 148 | } 149 | return cttk_u32_eq0(r); 150 | } 151 | 152 | /* see cttk.h */ 153 | int32_t 154 | cttk_array_cmp(const void *src1, const void *src2, size_t len) 155 | { 156 | const unsigned char *buf1, *buf2; 157 | uint32_t r; 158 | size_t u; 159 | 160 | buf1 = src1; 161 | buf2 = src2; 162 | r = 0; 163 | for (u = 0; u < len; u ++) { 164 | uint32_t z; 165 | 166 | /* 167 | * If the bytes are equal, then z is zero. 168 | * If buf1[u] > buf2[u], then z is in the 1..255 range. 169 | * If buf1[u] < buf2[u], then bits 8..31 of z are set to 1. 170 | */ 171 | z = buf1[u] - buf2[u]; 172 | 173 | /* 174 | * Set bit 8 to 1 if bits 0..7 are not all zero. 175 | */ 176 | z |= z + 0xFF; 177 | 178 | /* 179 | * At that point: 180 | * - If buf1[u] == buf2[u], then z == 0xFF. 181 | * - If buf1[u] < buf2[u], then bits 8..31 of z are all one. 182 | * - If buf1[u] > buf2[u], then bit 8 is one, and bits 9..31 183 | * are zero. 184 | * We just need to shift the result to remove the low 8 bits, 185 | * duplicating the sign bit as needed. 186 | */ 187 | z = (z >> 8) | (z & 0xFF000000); 188 | 189 | /* 190 | * If r is 1 or -1 at this point, then its low bit is set, 191 | * and "(r & 1) - 1" will be 0; in that case, r remains 192 | * unmodified. 193 | * 194 | * If r is 0, then "(r & 1) - 1" will be -1, and r is set 195 | * to the value of z (which is 0, 1 or -1). 196 | */ 197 | r |= (uint32_t)((r & 1) - 1) & z; 198 | } 199 | return *(int32_t *)&r; 200 | } 201 | -------------------------------------------------------------------------------- /src/hex.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 Thomas Pornin 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining 5 | * a copy of this software and associated documentation files (the 6 | * "Software"), to deal in the Software without restriction, including 7 | * without limitation the rights to use, copy, modify, merge, publish, 8 | * distribute, sublicense, and/or sell copies of the Software, and to 9 | * permit persons to whom the Software is furnished to do so, subject to 10 | * the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be 13 | * included in all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 19 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 20 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | #include "inner.h" 26 | 27 | /* see cttk.h */ 28 | int 29 | cttk_hexval(char c) 30 | { 31 | /* 32 | * Code below assumes an ASCII compatible charset. 33 | * 34 | * Decimal digits are 0x30 to 0x39. 35 | * Uppercase letters 'A' to 'F' are 0x41 to 0x46. 36 | * Lowercase letters 'a' to 'f' are 0x61 to 0x66. 37 | * 38 | * Only one of the three clauses (at most) will yield a non-zero 39 | * value; we increment it by 1 to get a value from 1 to 16, or 0 40 | * if the source character is not an hexadecimal digit. A final 41 | * subtraction ensures that we get -1 on an invalid source digit. 42 | */ 43 | uint32_t x, y, z, r; 44 | 45 | x = (uint32_t)c - 0x30; 46 | y = (uint32_t)c - 0x41; 47 | z = (uint32_t)c - 0x61; 48 | r = ((x + 1) & -cttk_u32_lt(x, 10).v) 49 | | ((y + 11) & -cttk_u32_lt(y, 6).v) 50 | | ((z + 11) & -cttk_u32_lt(z, 6).v); 51 | return (int)r - 1; 52 | } 53 | 54 | /* see cttk.h */ 55 | char 56 | cttk_hexdigit(int x, int uppercase) 57 | { 58 | unsigned off; 59 | 60 | /* 61 | * 'off' is the offset to add to the character value if going 62 | * beyond '9' (0x39) so that a letter is obtained ('A' is 0x41, 63 | * 'a' is 0x61). 64 | */ 65 | off = (0x41 - 0x3A); 66 | if (!uppercase) { 67 | off += 0x20; 68 | } 69 | 70 | /* 71 | * If x >= 10, then the subtraction will yield upper bits of 72 | * value 0. 73 | */ 74 | return (char)(0x30 + x + (off & ~(((unsigned)x - 10) >> 8))); 75 | } 76 | 77 | /* see cttk.h */ 78 | size_t 79 | cttk_hexscan(const char *src, size_t src_len, int skipws) 80 | { 81 | size_t u; 82 | 83 | for (u = 0; u < src_len; u ++) { 84 | int c; 85 | 86 | c = src[u]; 87 | if (skipws && c <= 0x20) { 88 | continue; 89 | } 90 | if (cttk_hexval(c) < 0) { 91 | break; 92 | } 93 | } 94 | return u; 95 | } 96 | 97 | /* see cttk.h */ 98 | size_t 99 | cttk_hextobin_gen(void *dst, size_t dst_len, 100 | const char *src, size_t src_len, const char **err, unsigned flags) 101 | { 102 | size_t u, v; 103 | unsigned char *buf; 104 | int halfbyte; 105 | int acc; 106 | 107 | buf = dst; 108 | halfbyte = 0; 109 | acc = 0; 110 | v = 0; 111 | for (u = 0; u < src_len; u ++) { 112 | int c, d; 113 | 114 | /* 115 | * We read source characters as unsigned bytes, so that 116 | * values are positive and bytes beyond 0x7F are not 117 | * considered whitespace. 118 | */ 119 | c = *((const unsigned char *)src + u); 120 | d = cttk_hexval(c); 121 | 122 | /* 123 | * If the character is not an hex digit, it may be 124 | * whitespace to be ignored; otherwise, this is an 125 | * error to report. Padding of half-bytes must be applied 126 | * where necessary (in such a case, output buffer capacity 127 | * was already checked). 128 | */ 129 | if (d < 0) { 130 | if ((flags & CTTK_HEX_SKIP_WS) != 0 && c <= 32) { 131 | continue; 132 | } 133 | if (err != NULL) { 134 | *err = src + u; 135 | } 136 | if (halfbyte && (flags & CTTK_HEX_PAD_ODD) != 0) { 137 | if (buf != NULL) { 138 | buf[v] = acc; 139 | } 140 | v ++; 141 | } 142 | return v; 143 | } 144 | 145 | /* 146 | * We have a new digit. We either keep it in the accumulator 147 | * (first digit of the next byte) or store it into the output 148 | * buffer. 149 | * 150 | * Output buffer overflow is detected on the first digit, 151 | * not the second. 152 | */ 153 | if (halfbyte) { 154 | if (buf != NULL) { 155 | buf[v] = acc + d; 156 | } 157 | v ++; 158 | } else { 159 | if (buf != NULL && v == dst_len) { 160 | if (err != NULL) { 161 | *err = src + u; 162 | } 163 | return v; 164 | } 165 | acc = d << 4; 166 | } 167 | halfbyte = !halfbyte; 168 | } 169 | 170 | /* 171 | * This part is reached when the source string is finished. We 172 | * encountered no error so far. If there is a pending digit, 173 | * then we either pad it into a full byte, or report an error, 174 | * depending on the relevant flag. Note that output buffer 175 | * capacity was already checked when that first digit was read. 176 | */ 177 | if (halfbyte) { 178 | if ((flags & CTTK_HEX_PAD_ODD) != 0) { 179 | if (buf != NULL) { 180 | buf[v] = acc; 181 | } 182 | v ++; 183 | } else { 184 | if (err != NULL) { 185 | *err = src + src_len; 186 | } 187 | return v; 188 | } 189 | } 190 | if (err != NULL) { 191 | *err = NULL; 192 | } 193 | return v; 194 | } 195 | 196 | /* see cttk.h */ 197 | size_t 198 | cttk_bintohex_gen(char *dst, size_t dst_len, 199 | const void *src, size_t src_len, unsigned flags) 200 | { 201 | const unsigned char *buf; 202 | size_t u, v; 203 | int halflast, uppercase; 204 | 205 | if (dst == NULL) { 206 | return (src_len << 1); 207 | } 208 | 209 | /* 210 | * Special case: destination buffer has size 0; we cannot even 211 | * write the terminating null byte. 212 | */ 213 | if (dst_len == 0) { 214 | return 0; 215 | } 216 | 217 | /* 218 | * Adjust lengths. Three situations: 219 | * 220 | * - Destination is large enough for all characters. 221 | * - Destination is too short, but may accommodate an even number 222 | * of digits. 223 | * - Destination is too short, but may accommodate an odd number 224 | * of digits. 225 | */ 226 | halflast = 0; 227 | if (dst_len < (1 + (src_len << 1))) { 228 | if ((dst_len & 1) == 0) { 229 | src_len = (dst_len - 1) >> 1; 230 | halflast = 1; 231 | } else { 232 | src_len = dst_len >> 1; 233 | } 234 | } 235 | 236 | buf = src; 237 | v = 0; 238 | uppercase = (flags & CTTK_HEX_UPPERCASE) != 0; 239 | for (u = 0; u < src_len; u ++) { 240 | int x; 241 | 242 | x = buf[u]; 243 | dst[v ++] = cttk_hexdigit(x >> 4, uppercase); 244 | dst[v ++] = cttk_hexdigit(x & 15, uppercase); 245 | } 246 | if (halflast) { 247 | int x; 248 | 249 | x = buf[u]; 250 | dst[v ++] = cttk_hexdigit(x >> 4, uppercase); 251 | } 252 | dst[v] = 0; 253 | return v; 254 | } 255 | -------------------------------------------------------------------------------- /src/base64.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 Thomas Pornin 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining 5 | * a copy of this software and associated documentation files (the 6 | * "Software"), to deal in the Software without restriction, including 7 | * without limitation the rights to use, copy, modify, merge, publish, 8 | * distribute, sublicense, and/or sell copies of the Software, and to 9 | * permit persons to whom the Software is furnished to do so, subject to 10 | * the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be 13 | * included in all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 19 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 20 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | #include "inner.h" 26 | 27 | /* 28 | * Return the value of a Base64 character. This is -1 if the character 29 | * is not a Base64 character; otherwise, the value ranges from 0 to 63. 30 | */ 31 | static int 32 | b64val(char c) 33 | { 34 | uint32_t p, q, r, z; 35 | 36 | p = (uint32_t)c - 0x41; 37 | q = (uint32_t)c - 0x61; 38 | r = (uint32_t)c - 0x30; 39 | 40 | z = ((p + 1) & -cttk_u32_lt(p, 26).v) 41 | | ((q + 27) & -cttk_u32_lt(q, 26).v) 42 | | ((r + 53) & -cttk_u32_lt(r, 10).v) 43 | | (63 & -cttk_u32_eq((uint32_t)c, 0x2B).v) 44 | | (64 & -cttk_u32_eq((uint32_t)c, 0x2F).v); 45 | return (int)z - 1; 46 | } 47 | 48 | /* see cttk.h */ 49 | size_t 50 | cttk_b64tobin_gen(void *dst, size_t dst_len, 51 | const char *src, size_t src_len, const char **err, unsigned flags) 52 | { 53 | unsigned char *buf; 54 | unsigned acc; 55 | size_t u, v; 56 | int lc; 57 | int nows; 58 | 59 | buf = dst; 60 | acc = 0; 61 | lc = 0; 62 | nows = (flags & CTTK_B64DEC_NO_WS) != 0; 63 | for (u = 0, v = 0; u < src_len; u ++) { 64 | int c, d; 65 | 66 | /* 67 | * We want source characters in the 0x00..0xFF range, 68 | * hence the cast to unsigned char. 69 | */ 70 | c = *((const unsigned char *)src + u); 71 | d = b64val(c); 72 | 73 | /* 74 | * If the character is not an hex digit, then it may be 75 | * whitespace to be ignored. 76 | */ 77 | if (d < 0) { 78 | if (!nows && c <= 32) { 79 | continue; 80 | } 81 | if (c == 0x3D && !(flags & CTTK_B64DEC_NO_PAD)) { 82 | /* 83 | * We found an '=' sign. 84 | * 85 | * We report an error if there are accumulated 86 | * non-zero bits. Note that these bits are 87 | * erroneous, hence we allow them to leak. 88 | */ 89 | if (lc < 2 || acc != 0) { 90 | goto b64dec_err; 91 | } 92 | for (u ++; u < src_len; u ++) { 93 | c = *((const unsigned char *)src + u); 94 | if (lc == 2 && c == 0x3D) { 95 | lc ++; 96 | continue; 97 | } 98 | if (c > 32 || nows) { 99 | goto b64dec_err; 100 | } 101 | } 102 | if (lc == 2) { 103 | goto b64dec_err; 104 | } 105 | if (err != NULL) { 106 | *err = NULL; 107 | } 108 | return v; 109 | } 110 | goto b64dec_err; 111 | } 112 | 113 | /* 114 | * Accumulate extra character. 115 | */ 116 | acc = (acc << 6) | (unsigned)d; 117 | 118 | /* 119 | * Output a byte, if possible. 120 | * 121 | * Some extra explanations are required about the management 122 | * of a short output buffer. When there is no room left 123 | * in the output buffer, the first character on which the 124 | * problem is detected depends on the position in the current 125 | * 4-character chunk: 126 | * 127 | * - When reading the first character of a chunk, if the 128 | * output buffer is full, then we know there is a problem. 129 | * Note that we don't have a full byte to store at this 130 | * point. 131 | * 132 | * - When reading the second character of a chunk, and 133 | * (after producing the first byte) we still have some 134 | * buffered non-zero bits, and the output buffer is now 135 | * full, then again a failure is inevitable. 136 | * 137 | * - Similarly when reading the third character of a chunk, 138 | * two bytes have been produced, and there are buffered 139 | * non-zero bits, which implies that a third byte will be 140 | * produced. 141 | * 142 | * However, the above implies that in some cases, the 143 | * error will be reported on a source character that 144 | * depends on the value of some data bits -- which are a 145 | * priori perfectly normal data bits, not erroneous 146 | * bits. We are talking here about an output buffer 147 | * being too short for a given input string. Constant-time 148 | * processing requires that we do not indulge in 149 | * memory activity that depends on secret data bits, and 150 | * this includes conditional jumps. Therefore, we MUST NOT 151 | * report an error based on the value of these buffered 152 | * bits. In these cases, the error reporting will be delayed 153 | * to the processing of the next input character. 154 | * 155 | * Thus, the test on a full output buffer shall be done 156 | * when reading characters 0, 2 and 3. We _can_ do it when 157 | * reading character 1, since it would have been trapped 158 | * at character 0 anyway. We may thus do the test 159 | * systematically. 160 | */ 161 | if (buf != NULL && v >= dst_len) { 162 | goto b64dec_err; 163 | } 164 | if (lc != 0) { 165 | unsigned out; 166 | 167 | if (lc == 1) { 168 | out = acc >> 4; 169 | acc &= 0x0F; 170 | } else if (lc == 2) { 171 | out = acc >> 2; 172 | acc &= 0x03; 173 | } else { 174 | out = acc; 175 | acc = 0; 176 | } 177 | if (buf != NULL) { 178 | buf[v] = out; 179 | } 180 | v ++; 181 | } 182 | lc = (lc + 1) & 3; 183 | } 184 | 185 | /* 186 | * Reached end of source string. Whether this is OK depends on 187 | * the state and flags: 188 | * 189 | * - If padding is expected, then this is correct only if we 190 | * processed an integral number of chunks. 191 | * 192 | * - If padding is not expected, then this is correct only if 193 | * the current chunk is not 1 lone character, and there are 194 | * no non-zero extra bits. 195 | * 196 | * In that case, we can test for the value of the extra bits, 197 | * since they are erroenous, thus not part of the actually secret 198 | * data. 199 | */ 200 | if (flags & CTTK_B64DEC_NO_PAD) { 201 | if (lc == 1 || acc != 0) { 202 | goto b64dec_err; 203 | } 204 | } else { 205 | if (lc != 0) { 206 | goto b64dec_err; 207 | } 208 | } 209 | if (err != NULL) { 210 | *err = NULL; 211 | } 212 | return v; 213 | 214 | b64dec_err: 215 | if (err != NULL) { 216 | *err = src + u; 217 | } 218 | return v; 219 | } 220 | 221 | static char 222 | b64char(uint32_t x) 223 | { 224 | /* 225 | * Values 0 to 25 map to 0x41..0x5A ('A' to 'Z') 226 | * Values 26 to 51 map to 0x61..0x7A ('a' to 'z') 227 | * Values 52 to 61 map to 0x30..0x39 ('0' to '9') 228 | * Value 62 maps to 0x2B ('+') 229 | * Value 63 maps to 0x2F ('/') 230 | */ 231 | uint32_t a, b, c; 232 | 233 | a = x - 26; 234 | b = x - 52; 235 | c = x - 62; 236 | 237 | /* 238 | * Looking at bits 8..15 of values a, b and c: 239 | * 240 | * x a b c 241 | * --------------------- 242 | * 0..25 FF FF FF 243 | * 26..51 00 FF FF 244 | * 52..61 00 00 FF 245 | * 62..63 00 00 00 246 | */ 247 | return (char)(((x + 0x41) & ((a & b & c) >> 8)) 248 | | ((x + (0x61 - 26)) & ((~a & b & c) >> 8)) 249 | | ((x - (52 - 0x30)) & ((~a & ~b & c) >> 8)) 250 | | ((0x2B + ((x & 1) << 2)) & (~(a | b | c) >> 8))); 251 | } 252 | 253 | /* see cttk.h */ 254 | size_t 255 | cttk_bintob64_gen(char *dst, size_t dst_len, 256 | const void *src, size_t src_len, unsigned flags) 257 | { 258 | size_t num, lc, dlen, u, v, n, line_len; 259 | const unsigned char *buf; 260 | 261 | /* 262 | * Compute total output length (not counting the terminating 0). 263 | */ 264 | num = src_len / 3; 265 | lc = src_len % 3; 266 | dlen = num << 2; 267 | if (lc != 0) { 268 | if (flags & CTTK_B64ENC_NO_PAD) { 269 | dlen += lc + 1; 270 | } else { 271 | dlen += 4; 272 | } 273 | } 274 | if (src_len != 0 && (flags & CTTK_B64ENC_NEWLINE) != 0) { 275 | size_t nl; 276 | 277 | if (flags & CTTK_B64ENC_LINE64) { 278 | nl = (dlen + 63) >> 6; 279 | line_len = 16; 280 | } else { 281 | nl = (dlen + 75) / 76; 282 | line_len = 19; 283 | } 284 | if (flags & CTTK_B64ENC_CRLF) { 285 | nl <<= 1; 286 | } 287 | dlen += nl; 288 | } else { 289 | line_len = 0; 290 | } 291 | 292 | /* 293 | * Easy special cases. 294 | */ 295 | if (dst == NULL) { 296 | return dlen; 297 | } 298 | if (dst_len == 0) { 299 | return 0; 300 | } 301 | 302 | /* 303 | * We reserve one character in the output for the terminating 0. 304 | */ 305 | dst_len --; 306 | 307 | /* 308 | * Output characters. 309 | * u = index in source buffer 310 | * v = index in output buffer 311 | * n = size of current line (counted in groups of 3 bytes / 4 chars) 312 | */ 313 | buf = src; 314 | num *= 3; 315 | 316 | #define OUTC(z) do { \ 317 | if (v == dst_len) { \ 318 | goto b64enc_exit; \ 319 | } \ 320 | dst[v ++] = (z); \ 321 | } while (0) 322 | 323 | for (u = 0, v = 0, n = 0; u < num; u += 3) { 324 | uint32_t x; 325 | 326 | x = ((uint32_t)buf[u] << 16) 327 | | ((uint32_t)buf[u + 1] << 8) 328 | | (uint32_t)buf[u + 2]; 329 | OUTC(b64char(x >> 18)); 330 | OUTC(b64char((x >> 12) & 0x3F)); 331 | OUTC(b64char((x >> 6) & 0x3F)); 332 | OUTC(b64char(x & 0x3F)); 333 | if (++ n == line_len) { 334 | if (flags & CTTK_B64ENC_CRLF) { 335 | OUTC(0x0D); 336 | } 337 | OUTC(0x0A); 338 | n = 0; 339 | } 340 | } 341 | if (lc != 0 || n != 0) { 342 | if (lc == 1) { 343 | uint32_t x; 344 | 345 | x = buf[u]; 346 | OUTC(b64char(x >> 2)); 347 | OUTC(b64char((x << 4) & 0x3F)); 348 | if (!(flags & CTTK_B64ENC_NO_PAD)) { 349 | OUTC(0x3D); 350 | OUTC(0x3D); 351 | } 352 | } else if (lc == 2) { 353 | uint32_t x; 354 | 355 | x = ((uint32_t)buf[u] << 8) | (uint32_t)buf[u + 1]; 356 | OUTC(b64char(x >> 10)); 357 | OUTC(b64char((x >> 4) & 0x3F)); 358 | OUTC(b64char((x << 2) & 0x3F)); 359 | if (!(flags & CTTK_B64ENC_NO_PAD)) { 360 | OUTC(0x3D); 361 | } 362 | } 363 | if (flags & CTTK_B64ENC_NEWLINE) { 364 | if (flags & CTTK_B64ENC_CRLF) { 365 | OUTC(0x0D); 366 | } 367 | OUTC(0x0A); 368 | } 369 | } 370 | 371 | #undef OUTC 372 | 373 | b64enc_exit: 374 | dst[v] = 0; 375 | return v; 376 | } 377 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Constant-Time Toolkit 2 | 3 | _Constant-time code_ is a concept that has been developed in the area of 4 | cryptography since about 2005. It relates to the fact that 5 | implementations of cryptographic algorithms manipulate secret values, and 6 | if they do not do so with enough care, outsiders may obtain some 7 | information on such values through time-based side channels, e.g. by 8 | measuring the total time taken to perform a computation. Memory caches, 9 | as commonly used in modern computers, are a great source of such leaks. 10 | We thus call "constant-time" implementations that take care not to 11 | allow time-based side channels. 12 | 13 | The concept of side channels is not restricted to cryptography. In fact, 14 | any piece of code that processes confidential data, in a context where 15 | attackers may make precise timing measures, is potentially vulnerable, 16 | and should use mitigation measures. In particular, implementations of 17 | security enclaves with [Intel SGX](https://software.intel.com/en-us/sgx) 18 | or [ARM TrustZone](https://developer.arm.com/technologies/trustzone) 19 | operate in a security model where side channel attacks are very 20 | effective, since the attacker is supposed to run his own code on the 21 | host system and can monitor cache accesses with great accuracy. 22 | Constant-time coding techniques are highly relevant to about anything 23 | that is implemented in an enclave. 24 | 25 | This library, called CTTK, is **a collection of constant-time 26 | implementations of primitive operations that may help in writing 27 | constant-time code, including non-cryptographic constant-time code.** 28 | 29 | It shall be noted that the expression "constant-time" is traditional but 30 | slightly confusing: constant-time code does not always execute in a 31 | constant amount of time; rather, this means that any variation in 32 | execution time is uncorrelated with secret information. For more 33 | information on constant-time coding, you may have a look at the 34 | [Cryptography Coding 35 | Standard](https://cryptocoding.net/index.php/Cryptography_Coding_Standard) 36 | pages, and the [BearSSL 37 | library](https://www.bearssl.org/constanttime.html). 38 | 39 | # License 40 | 41 | This library uses the MIT license. In plain words, this means that you 42 | can reuse it in both opensource and proprietary projects; the only 43 | requirement is that you keep the license text with each source file, 44 | where it already is. This is for my protection: the license text 45 | basically says that whatever happens, it's not my fault, and you 46 | understand it. 47 | 48 | This library is written and maintained by Thomas Pornin 49 | ``. Any comments and suggestions are welcome. Be 50 | warned that if you submit a patch or pull request, and I find it good, 51 | then I will still rewrite it completely, because I am a raving maniac. 52 | 53 | # Status 54 | 55 | CTTK is still very early in its development. It probably contains some 56 | bugs. The API _may_ change in future versions. I will do my best not to 57 | gratuitously break source or binary compatibility, but I cannot 58 | guarantee that it won't happen. 59 | 60 | **WARNING:** IF YOU ARE TRYING TO USE THIS LIBRARY, IN ITS CURRENT STATE, 61 | FOR PRODUCTION CODE, THEN YOU ARE MOST CERTAINLY CRAZY. Of course, a 62 | solid dose of craziness is often needed to promote innovation; but it 63 | rarely ends well for the zealous early adopter. 64 | 65 | A list of planned features and improvement can be seen in the 66 | [TODO.md](TODO.md) file. 67 | 68 | # Compilation 69 | 70 | To compile, type `make`. This should work on any decent Linux or \*BSD 71 | system, both with GNU make and BSD make. If you use Microsoft Visual C 72 | command-line tools on Windows, you may type `nmake`, and it should work 73 | too. You can tune compile-time options in the relevant file in the 74 | `conf` directory; these can also be added on the compilation command-line, 75 | e.g.: 76 | 77 | make BUILD=alt 78 | 79 | will create a directory called `alt` and put the compilation output in 80 | that directory instead of the default directory `build`. 81 | 82 | There are some tunable configuration options in `src/config.h`. Such 83 | options may be set either in that file, or through command-line options 84 | for compilation (in the `CFLAGS` variable). 85 | 86 | Compilation produces a static library (`libcttk.a` on Unix-like systems, 87 | `cttks.lib` on Windows), a dynamic library (`libcttk.so` on Unix-like 88 | system, `cttk.dll` on Windows), and a test executable (`testcttk`), all 89 | in the build directory, which is created when needed (its default name 90 | is `build`). The test executable can be run to perform some basic 91 | self-tests. 92 | 93 | There is no automated installation process yet; notably, in the context 94 | of security enclaves such as SGX, a specific installation process would 95 | be needed anyway. The external API is the `cttk.h` file located in the 96 | `inc` directory. 97 | 98 | If using the provided makefiles is inconvenient, the files may be 99 | integrated in any other build system. The dependencies are simple: 100 | 101 | - Every `.c` file in `src` should be compiled into an object file. 102 | - Each such `.c` file includes `inner.h`, `config.h`, and `cttk.h`. 103 | - There are no other dependencies. 104 | 105 | # API 106 | 107 | CTTK is a C library. As a rule, C is a tricky language, full of 108 | pitfalls, in particular undefined behaviours that may break any 109 | implementation silently when changing the compiler version. More modern, 110 | safer languages such as [Rust](https://www.rust-lang.org/en-US/) or 111 | [Go](https://golang.org/) are almost always preferable; and even for 112 | very low-level, bare metal processing, it makes sense to explore 113 | alternatives such as [Forth](http://wiki.c2.com/?ForthLanguage). 114 | 115 | On the other hand, C is still the _lingua franca_ of programming 116 | languages, and a C compiler can be found for just about any hardware and 117 | software environment. Moreover, in an ideal world, languages that are 118 | under active development should integrate constant-time primitives as 119 | part of the standard language definition; a third-party library like 120 | CTTK makes sense only because C is a mostly frozen language. 121 | 122 | CTTK is supposed to be usable from C++ as well, but with its C-like API. 123 | There is no support for operator overloading or templates. 124 | 125 | The API is mostly documented in the `cttk.h` file itself. An HTML 126 | version of that documentation can be produced with 127 | [Doxygen](http://www.doxygen.org); a configuration file (`Doxyfile`) 128 | is provided. 129 | 130 | ## Namespaces 131 | 132 | C has no namespace. Therefore, all external names provided by CTTK start 133 | with a specific prefix to help with avoiding name collisions. 134 | 135 | All objects with external linkage (functions, global variables) have a 136 | name that starts with `cttk_`. 137 | 138 | The header file (`cttk.h`) also defines function and macro names that 139 | start with `cttk_`, `CTTK_` or `cti_`. These names only impact the 140 | current translation unit, i.e. the files that include directly or 141 | indirectly `cttk.h`. 142 | 143 | ## Header 144 | 145 | To use CTTK in your application, include the `cttk.h` header. That file 146 | pulls in a few standard library files that should be available on all C 147 | implementations, including "freestanding" compilers for embedded 148 | systems. 149 | 150 | ## Booleans 151 | 152 | CTTK defines the `cttk_bool` type to contain a boolean value (true or 153 | false). This type is defined as a `struct` so that it is NOT directly 154 | usable to control conditional jumps, since these are, by definition, 155 | not constant-time. 156 | 157 | The `cttk_true` and `cttk_false` constants are provided for, 158 | respectively, true and false values. 159 | 160 | The `cttk_bool_of_u32()`, `cttk_bool_of_s32()` and `cttk_bool_to_int()` 161 | functions can be used to convert between C "booleans" (i.e. integer 162 | values 0 and 1) and CTTK booleans. Constant-time code should endeavour 163 | to apply such conversions only when the boolean value is no longer 164 | considered secret. 165 | 166 | Boolean operations are implemented by `cttk_not()`, `cttk_and()`, 167 | `cttk_or()`, `cttk_xor()` and `cttk_eqv()` (this last one is also 168 | known as the "XORNOT" operation). 169 | 170 | ## Native Integers 171 | 172 | Primitives for doing constant-time comparisons on native integers are 173 | provided. In all names, `s32`, `u32`, `s64` and `u64` designate the C 174 | types `int32_t`, `uint32_t`, `int64_t` and `uint64_t`, respectively. 175 | Variants for all applicable types are provided, for the following 176 | operations: 177 | 178 | - Multiplexer (selection of one of two operands, based on a `cttk_bool` 179 | value): `cttk_s32_mux`, `cttk_u32_mux`, `cttk_s64_mux`, `cttk_u64_mux` 180 | 181 | - Comparison with zero (returns true if the operand is not zero): 182 | `cttk_s32_neq0`, `cttk_u32_neq0`, `cttk_s64_neq0`, `cttk_u64_neq0` 183 | 184 | - Comparison with zero (returns true if the operand is zero): 185 | `cttk_s32_eq0`, `cttk_u32_eq0`, `cttk_s64_eq0`, `cttk_u64_eq0` 186 | 187 | - Equality comparison between two integers: 188 | `cttk_s32_eq`, `cttk_u32_eq`, `cttk_s64_eq`, `cttk_u64_eq` 189 | 190 | - Inequality comparison between two integers: 191 | `cttk_s32_neq`, `cttk_u32_neq`, `cttk_s64_neq`, `cttk_u64_neq` 192 | 193 | - Ordering ("greater than"): 194 | `cttk_s32_gt`, `cttk_u32_gt`, `cttk_s64_gt`, `cttk_u64_gt` 195 | 196 | - Ordering ("greater or equal"): 197 | `cttk_s32_geq`, `cttk_u32_geq`, `cttk_s64_geq`, `cttk_u64_geq` 198 | 199 | - Ordering ("lower than"): 200 | `cttk_s32_lt`, `cttk_u32_lt`, `cttk_s64_lt`, `cttk_u64_lt` 201 | 202 | - Ordering ("lower or equal"): 203 | `cttk_s32_leq`, `cttk_u32_leq`, `cttk_s64_leq`, `cttk_u64_leq` 204 | 205 | - Generic comparison (returns -1, 0 or 1): 206 | `cttk_s32_cmp`, `cttk_u32_cmp`, `cttk_s64_cmp`, `cttk_u64_cmp` 207 | 208 | - Comparison with zero ("greater than zero"): 209 | `cttk_s32_gt0`, `cttk_s64_gt0` 210 | 211 | - Comparison with zero ("greater than or equal to zero"): 212 | `cttk_s32_geq0`, `cttk_s64_geq0` 213 | 214 | - Comparison with zero ("lower than zero"): 215 | `cttk_s32_lt0`, `cttk_s64_lt0` 216 | 217 | - Comparison with zero ("lower than or equal to zero"): 218 | `cttk_s32_leq0`, `cttk_s64_leq0` 219 | 220 | - Generic sign extraction (-1, 0 or 1): 221 | `cttk_s32_sign`, `cttk_s64_sign` 222 | 223 | The `cttk_u32_bitlength()` function computes the length, in bits, of an 224 | unsigned 32-bit integer. The bit length of an integer _x_ is the 225 | smallest integer _k_ such that _x_ is lower than two raised to the power 226 | _k_. 227 | 228 | ## Hexadecimal Encoding And Decoding 229 | 230 | `cttk_hextobin_gen` parses hexadecimal digits into binary. 231 | `cttk_bintohex_gen` performs the reverse operation: encoding binary 232 | data into hexadecimal. These functions are tunable: 233 | 234 | - Decoding may tolerate, or not, intervening whitespace. 235 | - Decoding may accept, or not, input data with an odd number of 236 | hexadecimal digits (a trailing `'0'` is then assumed to complete 237 | the last byte). 238 | - Encoding may use uppercase or lowercase letters. 239 | 240 | The implementation protects the value of bytes and digits from 241 | outsiders. It cannot, however, hide the _number_ of hexadecimal digits 242 | or the length, in bytes, of the binary data. If whitespace is accepted 243 | (and ignored), then location of whitespace within the source string may 244 | conceptually leak as well. 245 | 246 | ## Base64 Encoding And Decoding 247 | 248 | `cttk_bintob64_gen` encode binary data into Base64 characters. Tunable 249 | options are: 250 | 251 | - Output may be broken into lines. The line end is either an LF 252 | (0x0A), or a CR+LF sequence (0x0D 0x0A). Line length is either 253 | 76 or 64 data characters. 254 | 255 | - The padding characters (one or two "`=`" signs when the input length 256 | is not a multiple of 3) may be produced or omitted. 257 | 258 | `cttk_b64tobin_gen` parses Base64 characters into binary. The function 259 | may tolerate (and ignore) whitespace characters; but it can also be 260 | instructed to report errors on any extra character, including 261 | whitespace. The padding characters are normally expected and processed, 262 | but the decoder can also be configured to not use padding. 263 | 264 | As for the hexadecimal decoder, the data byte contents are protected 265 | from outsiders. The data size, and position of data characters and 266 | whitespace within an incoming stream, may leak. 267 | 268 | ## Native Integer Multiplications 269 | 270 | Not all CPU provide constant-time multiplication opcodes; see 271 | [this page](https://www.bearssl.org/ctmul.html) for details. CTTK 272 | provide some constant-time multiplication primitives: 273 | 274 | - `cttk_mulu32()`: multiplication of two 32-bit unsigned integers, 275 | with a 32-bit result (the low 32 bits of the result). 276 | 277 | - `cttk_muls32()`: multiplication of two 32-bit signed integers, 278 | with a 32-bit result (truncation to the low 32 bits). Note that 279 | in plain C, overflows on signed integers trigger undefined 280 | behaviour; with CTTK, truncation is guaranteed. 281 | 282 | - `cttk_mulu32w()`: multiplication of two 32-bit unsigned integers, 283 | with a 64-bit result (`uint64_t`). 284 | 285 | - `cttk_muls32w()`: multiplication of two 32-bit signed integers, 286 | with a 64-bit result (`int64_t`). 287 | 288 | - `cttk_mulu64()`: multiplication of two 64-bit unsigned integers, 289 | with a 64-bit result (the low 64 bits of the result). 290 | 291 | - `cttk_muls64()`: multiplication of two 64-bit signed integers, 292 | with a 64-bit result (truncation to the low 64 bits). As for 293 | `cttk_muls32()`, CTTK guarantees truncating behaviour. 294 | 295 | The default implementation of these functions is (nominally) 296 | constant-time on all architectures, but not very efficient. Some 297 | compile-time options (see `config.h`) can be used to force use of the 298 | native multiplication operator, if you are certain that your code will 299 | always run on hardware platforms that provide constant-time 300 | multiplications (the gist of the Web page linked to above is that such a 301 | bet is risky). 302 | 303 | ## Big Integers 304 | 305 | CTTK provides a constant-time implementation of big integers with a 306 | configurable size. In fact, _several_ implementations are planned, for 307 | better performance on various architectures; application code should use 308 | the generic macros that will select the "right one" automatically. 309 | 310 | A big integer value has the following characteristics: 311 | 312 | - It has a defined _size_ which qualifies the space in which the 313 | value exists. The size is expressed in bits. If the size is _n_ 314 | bits, then the value may range between `-2**(n-1)` and `2**(n-1)-1` 315 | (where "`**`" stands for exponentiation). All bit sizes, starting 316 | from 1, are supported. For instance, you can have 17-bit integers. 317 | Note that the size includes the sign bit; thus, 16-bit integers 318 | will range from -32768 to +32767. There is no upper limit for the 319 | bit size except available RAM. 320 | 321 | - Each value may be either an integer in the defined range, or a NaN 322 | ("not a number"). A NaN is obtained whenever the mathematical result 323 | of an operation is not representable in the defined range (except 324 | for the operations that are explicitly defined as "truncating"). 325 | NaNs propagate: if an operand to an arithmetic operation is a NaN, 326 | then the result will also be a NaN. 327 | 328 | - The C type for a big integer is an array. The `cti_def` macro is 329 | used to declare a local variable or structure field that is 330 | large enough for big integers up to a given size. Since that type 331 | is an array, it is automatically passed by reference to called 332 | functions. 333 | 334 | - To become usable, the big integer object must be initialized with 335 | `cti_init()` (alternatively, it may be declared and initialized as a 336 | local variable with the `cti_definit` macro). Initialization sets 337 | the value to NaN but also encodes the actual size of the integer. 338 | Using an uninitialized big integer with any of the functions may 339 | trigger "bad things" such as buffer overflows. 340 | 341 | - Big integers do not grow or shrink. They do not involve dynamic 342 | memory allocation either. Thus, there is no "release" function. 343 | They can be forgotten just like any plain local variable. 344 | 345 | The following rules are applicable to all big integer functions: 346 | 347 | - The function name starts with `cti_`. 348 | 349 | - All these function names are actually macros that map to the 350 | selected implementation functions. 351 | 352 | - Some of the functions may be inline functions, for better 353 | performance. 354 | 355 | - Destination operands come before source operands. This mimics 356 | mathematical notation (in "d = a + b", the destination is on 357 | the left) and established usage in the C standard library 358 | (e.g. the `memcpy()` function). 359 | 360 | - All operand overlaps are allowed; that is, it is permitted 361 | to write things such as `cti_mul(x, x, y)` to perform a 362 | multiplication of `x` by `y` and write the result in `x`. 363 | 364 | - Some operations internally need temporary buffers. These will 365 | be usually stack-allocated, but for large integers, `malloc()` 366 | is used. This is transparent to applications: the buffers are 367 | released before returning to the caller. For the benefit of 368 | embedded systems which might not have a `malloc()`, it is 369 | possible to disable use of that function with the compile-time 370 | option `CTTK_NO_MALLOC`. If `malloc()` was disabled or failed 371 | to allocate the required memory, then the result will be set 372 | to NaN. 373 | 374 | - If operand sizes do not match (both source and destination), 375 | then the result is set to NaN. 376 | 377 | - Constant-time protection is on the integer values, not the 378 | sizes. The "size" here is not the actual bit length of the value 379 | (that information is protected) but the representable range 380 | used by the containing variable. Similarly, the location in RAM 381 | of any value cannot be protected. 382 | 383 | - Whether an integer value is NaN or not is protected against 384 | time-based side channels. The `cti_isnan()` function returns 385 | the NaN status of an integer as a `cttk_bool`. 386 | 387 | - For shift operators, default functions (e.g. `cti_lsh()`) protect 388 | the values of the source integer and the result value, but not the 389 | shift count. If the shift count is also secret, then alternate 390 | implementations are provided (`cti_lsh_prot()`...) but they are 391 | substantially slower. 392 | 393 | An example of the use of CTTK big integer code is shown below. It is an 394 | implementation of a function that computes the average of many 64-bit 395 | integers, and prints the result in decimal (with a precision of 12 396 | digits in the fractional part). The individual values are considered 397 | secret, while the average is not. (This example is not meant to be 398 | realistic, but to demonstrate the usage syntax.) 399 | 400 | #include 401 | #include 402 | #include "cttk.h" 403 | 404 | void 405 | print_average(const uint64_t *values, uint64_t num) 406 | { 407 | /* 408 | * We may have up to 2^64 values of 64 bits each, thus a sum 409 | * of up to a bit less than 2^128. Since our big integers 410 | * are signed, we need 129-bit integers. 411 | */ 412 | cti_definit(s, 129); 413 | cti_definit(x, 129); 414 | uint64_t u, hi, lo; 415 | 416 | /* 417 | * Compute the sum of all integers in s. 418 | */ 419 | cti_set_u32(s, 0); 420 | for (u = 0; u < num; u ++) { 421 | cti_set_u64(x, values[u]); 422 | cti_add(s, s, x); 423 | } 424 | 425 | /* 426 | * Divide the sum by the number of integers. The quotient 427 | * will be the integral part of the average. 428 | */ 429 | cti_set_u64(x, num); 430 | cti_divrem(x, s, s, x); 431 | hi = cti_to_u64(x); 432 | 433 | /* 434 | * To get the fractional part, properly rounded to 12 435 | * digits, we multiply the remainder by 10^12, then 436 | * add num/2 (for rounding), and divide by num. 437 | */ 438 | cti_set_u64(x, 1000000000000); 439 | cti_mul(s, s, x); 440 | cti_set_u64(x, num >> 1); 441 | cti_add(s, s, x); 442 | cti_set_u64(x, num); 443 | cti_div(x, s, x); 444 | lo = cti_to_u64(x); 445 | 446 | printf("avg = %llu.%012llu\n", 447 | (unsigned long long)hi, (unsigned long long)lo); 448 | } 449 | 450 | ## Oblivious RAM 451 | 452 | An _Oblivious RAM_ implementation allows array reads and writes in 453 | constant-time, i.e. without leaking information about the exchanged 454 | value or the access index. Currently, CTTK includes only a very basic 455 | implementation that has cost _O(N)_ for an array of size _N_: for every 456 | read or write operation, the full array memory is touched. The relevant 457 | functions are `ctty_array_read()` and `cttk_array_write()`. 458 | 459 | Implementations of more efficient ORAM algorithms are planned, but not 460 | yet done. 461 | 462 | Related functions are: 463 | 464 | - `cttk_cond_copy()`: constant-time copy of bytes, conditionally to 465 | a boolean flag. 466 | 467 | - `cttk_cond_swap()`: constant-time exchange of two non-overlapping 468 | values, conditionally to a boolean flag. 469 | 470 | - `cttk_array_cmp()`, `cttk_array_eq()` and `cttk_array_neq()`: 471 | constant-time comparisons of arrays of bytes (equality and 472 | lexicographic order). 473 | -------------------------------------------------------------------------------- /src/int31.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 Thomas Pornin 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining 5 | * a copy of this software and associated documentation files (the 6 | * "Software"), to deal in the Software without restriction, including 7 | * without limitation the rights to use, copy, modify, merge, publish, 8 | * distribute, sublicense, and/or sell copies of the Software, and to 9 | * permit persons to whom the Software is furnished to do so, subject to 10 | * the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be 13 | * included in all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 19 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 20 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | #include "inner.h" 26 | 27 | /* 28 | * Memory layout: a big integer is a sequence of 32 bit words. 29 | * First word (header) contains (least to most significant order): 30 | * 31 | * size % 31 5 bits, value is 0 to 30 32 | * size / 31 26 bits 33 | * NaN flag 1 bit (1 = NaN, 0 = not NaN) 34 | * 35 | * Further words contain the value, 31 bits per word, little-endian. 36 | * The upper bit of each uint32_t is always 0. The sign bit is extended 37 | * over the complete last word (excluding bit 31). 38 | * 39 | * If the NaN flag is set, then words may contain any value, with 40 | * the following constraints: 41 | * - The top bit of each word (except the header word) is still 0. 42 | * - The header word is still fully defined. 43 | * 44 | * Size is not secret, so we can make conditional jumps based on that 45 | * size. 46 | * 47 | * 48 | * Let h be the value of the header word, with the NaN flag masked out. 49 | * Then: 50 | * 51 | * - The number of value words is equal to: (h + 31) >> 5 52 | * - The bit length is: h - (h >> 5) 53 | */ 54 | 55 | /* 56 | * Get index of the top bit (sign bit) given the encoded size (header 57 | * word, without the "NaN" flag). The returned index is relative to 58 | * the top word. 59 | */ 60 | static inline unsigned 61 | top_index(uint32_t h) 62 | { 63 | h = (h & 31) - 1; 64 | return h + (31 & (h >> 5)); 65 | } 66 | 67 | /* 68 | * Sign-extend an n-bit value to 32 bits (1 <= n <= 32). 69 | */ 70 | static inline uint32_t 71 | signext(uint32_t v, unsigned n) 72 | { 73 | uint32_t hi, lo; 74 | 75 | hi = -(uint32_t)((v >> (n - 1)) & 1) << (n - 1); 76 | lo = v & ((uint32_t)-1 >> (32 - n)); 77 | return hi | lo; 78 | } 79 | 80 | /* see cttk.h */ 81 | void 82 | cttk_i31_init(uint32_t *x, unsigned size) 83 | { 84 | uint32_t h; 85 | 86 | h = (uint32_t)size + ((uint32_t)size / 31); 87 | *x = h | 0x80000000; 88 | memset(x + 1, 0, ((h + 31) >> 5) * sizeof *x); 89 | } 90 | 91 | /* see cttk.h */ 92 | void 93 | cttk_i31_set_u32(uint32_t *x, uint32_t v) 94 | { 95 | uint32_t h, size; 96 | size_t len; 97 | 98 | x[0] &= 0x7FFFFFFF; 99 | h = x[0]; 100 | len = (h + 31) >> 5; 101 | size = h - (h >> 5); 102 | 103 | /* 104 | * If there is an overflow, then we will get a NaN. Otherwise, 105 | * the value is positive, so the sign extends as a 0. 106 | */ 107 | memset(x + 2, 0, (len - 1) * sizeof(uint32_t)); 108 | x[1] = v & 0x7FFFFFFF; 109 | if (size >= 32) { 110 | x[2] = v >> 31; 111 | } 112 | if (size <= 32) { 113 | x[0] |= cttk_u32_neq0(v >> (size - 1)).v << 31; 114 | } 115 | } 116 | 117 | /* see cttk.h */ 118 | void 119 | cttk_i31_set_u32_trunc(uint32_t *x, uint32_t v) 120 | { 121 | uint32_t h, size; 122 | size_t len; 123 | 124 | x[0] &= 0x7FFFFFFF; 125 | h = x[0]; 126 | len = (h + 31) >> 5; 127 | size = h - (h >> 5); 128 | memset(x + 1, 0, len * sizeof(uint32_t)); 129 | if (size > 32) { 130 | x[1] = v & 0x7FFFFFFF; 131 | x[2] = v >> 31; 132 | } else if (size == 32) { 133 | x[1] = v & 0x7FFFFFFF; 134 | x[2] = -(v >> 31) >> 1; 135 | } else { 136 | x[1] = signext(v, size) & 0x7FFFFFFF; 137 | } 138 | } 139 | 140 | /* see cttk.h */ 141 | void 142 | cttk_i31_set_u64(uint32_t *x, uint64_t v) 143 | { 144 | uint32_t h, size; 145 | size_t len; 146 | 147 | x[0] &= 0x7FFFFFFF; 148 | h = x[0]; 149 | len = (h + 31) >> 5; 150 | size = h - (h >> 5); 151 | memset(x + 1, 0, len * sizeof(uint32_t)); 152 | x[1] = (uint32_t)v & 0x7FFFFFFF; 153 | if (size > 31) { 154 | x[2] = (uint32_t)(v >> 31) & 0x7FFFFFFF; 155 | } 156 | if (size > 62) { 157 | x[3] = (uint32_t)(v >> 62); 158 | } 159 | if (size <= 64) { 160 | x[0] |= cttk_u64_neq0(v >> (size - 1)).v << 31; 161 | } 162 | } 163 | 164 | /* see cttk.h */ 165 | void 166 | cttk_i31_set_u64_trunc(uint32_t *x, uint64_t v) 167 | { 168 | uint32_t h, size; 169 | size_t len; 170 | 171 | x[0] &= 0x7FFFFFFF; 172 | h = x[0]; 173 | len = (h + 31) >> 5; 174 | size = h - (h >> 5); 175 | memset(x + 1, 0, len * sizeof(uint32_t)); 176 | if (size >= 65) { 177 | /* 178 | * If size is 65 bits or more, then the 64-bit value fits 179 | * unmodified (positive). 180 | */ 181 | x[1] = (uint32_t)v & 0x7FFFFFFF; 182 | x[2] = (uint32_t)(v >> 31) & 0x7FFFFFFF; 183 | x[3] = (uint32_t)(v >> 62); 184 | } else if (size >= 63) { 185 | /* 186 | * If size is 63 or 64 bits, then the value uses three 187 | * words; we must truncate and sign-extend the top word. 188 | */ 189 | x[1] = (uint32_t)v & 0x7FFFFFFF; 190 | x[2] = (uint32_t)(v >> 31) & 0x7FFFFFFF; 191 | x[3] = signext((uint32_t)(v >> 62), size - 62) & 0x7FFFFFFF; 192 | } else if (size >= 32) { 193 | /* 194 | * If size is 32 to 62 bits, then the value uses two 195 | * words; we must truncate and sign-extend the top word. 196 | */ 197 | x[1] = (uint32_t)v & 0x7FFFFFFF; 198 | x[2] = signext((uint32_t)(v >> 31), size - 31) & 0x7FFFFFFF; 199 | } else { 200 | x[1] = signext((uint32_t)v, size) & 0x7FFFFFFF; 201 | } 202 | } 203 | 204 | /* see cttk.h */ 205 | void 206 | cttk_i31_set_s32(uint32_t *x, int32_t v) 207 | { 208 | uint32_t h, size; 209 | size_t u, len; 210 | uint32_t w; 211 | 212 | x[0] &= 0x7FFFFFFF; 213 | h = x[0]; 214 | len = (h + 31) >> 5; 215 | size = h - (h >> 5); 216 | w = (uint32_t)v; 217 | x[1] = w & 0x7FFFFFFF; 218 | 219 | /* 220 | * If size is at least 32 bits, then there can be no overflow, 221 | * but we must extend the sign bit over all remaining words. 222 | * If size is 31 bits or less, then we check that all top bits 223 | * of the source value are equal to each other. 224 | */ 225 | if (size >= 32) { 226 | w = -(w >> 31) >> 1; 227 | for (u = 1; u < len; u ++) { 228 | x[u + 1] = w; 229 | } 230 | } else { 231 | uint32_t m; 232 | 233 | m = (uint32_t)-1 << (size - 1); 234 | w &= m; 235 | x[0] |= (cttk_u32_neq0(w).v & cttk_u32_neq0(w ^ m).v) << 31; 236 | } 237 | } 238 | 239 | /* see cttk.h */ 240 | void 241 | cttk_i31_set_s64(uint32_t *x, int64_t v) 242 | { 243 | uint32_t h, size; 244 | size_t u, len; 245 | uint64_t w; 246 | 247 | x[0] &= 0x7FFFFFFF; 248 | h = x[0]; 249 | len = (h + 31) >> 5; 250 | size = h - (h >> 5); 251 | w = (uint64_t)v; 252 | x[1] = (uint32_t)w & 0x7FFFFFFF; 253 | if (size >= 63) { 254 | uint32_t h; 255 | 256 | x[2] = (uint32_t)(w >> 31) & 0x7FFFFFFF; 257 | x[3] = signext((uint32_t)(w >> 62), 2) & 0x7FFFFFFF; 258 | h = -(uint32_t)(w >> 63) >> 1; 259 | for (u = 3; u < len; u ++) { 260 | x[u + 1] = h; 261 | } 262 | } else if (size >= 32) { 263 | x[2] = (uint32_t)(w >> 31) & 0x7FFFFFFF; 264 | } 265 | 266 | /* 267 | * Check on overflow: the top bits must be equal to each other. 268 | */ 269 | if (size < 64) { 270 | uint64_t m; 271 | 272 | m = (uint64_t)-1 << (size - 1); 273 | w &= m; 274 | x[0] |= (cttk_u64_neq0(w).v & cttk_u64_neq0(w ^ m).v) << 31; 275 | } 276 | } 277 | 278 | /* see cttk.h */ 279 | void 280 | cttk_i31_set(uint32_t *d, const uint32_t *a) 281 | { 282 | uint32_t h; 283 | size_t dlen, alen; 284 | 285 | /* 286 | * Special case: when source and operands are identical, there 287 | * is nothing more to do. 288 | */ 289 | if (a == d) { 290 | return; 291 | } 292 | 293 | /* 294 | * We may now assume that operands do not overlap. 295 | */ 296 | h = a[0] & 0x7FFFFFFF; 297 | alen = (h + 31) >> 5; 298 | 299 | h = d[0] & 0x7FFFFFFF; 300 | dlen = (h + 31) >> 5; 301 | d[0] = h | (a[0] & 0x80000000); 302 | 303 | if (dlen > alen) { 304 | size_t u; 305 | uint32_t w; 306 | 307 | memcpy(d + 1, a + 1, alen * sizeof *a); 308 | w = -(a[alen] >> 30) >> 1; 309 | for (u = alen; u < dlen; u ++) { 310 | d[1 + u] = w; 311 | } 312 | } else { 313 | size_t u; 314 | uint32_t w, m; 315 | 316 | memcpy(d + 1, a + 1, dlen * sizeof *a); 317 | m = -(a[alen] >> 30) >> 1; 318 | w = (d[dlen] ^ m) & ((uint32_t)-1 << top_index(h)); 319 | for (u = dlen; u < alen; u ++) { 320 | w |= a[u + 1] ^ m; 321 | } 322 | d[0] |= (w | -w) & 0x80000000; 323 | } 324 | } 325 | 326 | /* see cttk.h */ 327 | void 328 | cttk_i31_set_trunc(uint32_t *d, const uint32_t *a) 329 | { 330 | uint32_t h; 331 | size_t dlen, alen; 332 | 333 | /* 334 | * Special case: when source and operands are identical, there 335 | * is nothing more to do. 336 | */ 337 | if (a == d) { 338 | return; 339 | } 340 | 341 | /* 342 | * We may now assume that operands do not overlap. 343 | */ 344 | h = a[0] & 0x7FFFFFFF; 345 | alen = (h + 31) >> 5; 346 | 347 | h = d[0] & 0x7FFFFFFF; 348 | dlen = (h + 31) >> 5; 349 | d[0] = h | (a[0] & 0x80000000); 350 | 351 | if (dlen > alen) { 352 | size_t u; 353 | uint32_t w; 354 | 355 | memcpy(d + 1, a + 1, alen * sizeof *a); 356 | w = -(a[alen] >> 30) >> 1; 357 | for (u = alen; u < dlen; u ++) { 358 | d[1 + u] = w; 359 | } 360 | } else { 361 | uint32_t m, sb; 362 | 363 | memcpy(d + 1, a + 1, dlen * sizeof *a); 364 | m = (uint32_t)1 << top_index(h); 365 | sb = d[dlen] & m; 366 | d[dlen] &= m - 1; 367 | d[dlen] |= -sb & 0x7FFFFFFF; 368 | } 369 | } 370 | 371 | /* see cttk.h */ 372 | uint32_t 373 | cttk_i31_to_u32_trunc(const uint32_t *x) 374 | { 375 | uint32_t r; 376 | 377 | r = x[1]; 378 | if ((x[0] & 0x7FFFFFFF) > 32) { 379 | r |= x[2] << 31; 380 | } else { 381 | r |= (r & 0x40000000) << 1; 382 | } 383 | return r & (uint32_t)((x[0] >> 31) - 1); 384 | } 385 | 386 | /* see cttk.h */ 387 | int32_t 388 | cttk_i31_to_s32_trunc(const uint32_t *x) 389 | { 390 | uint32_t r; 391 | 392 | r = cttk_i31_to_u32_trunc(x); 393 | return *(int32_t *)&r; 394 | } 395 | 396 | /* see cttk.h */ 397 | uint64_t 398 | cttk_i31_to_u64_trunc(const uint32_t *x) 399 | { 400 | uint32_t h; 401 | uint64_t r; 402 | 403 | h = x[0] & 0x7FFFFFFF; 404 | r = x[1]; 405 | if (h > 64) { 406 | r |= (uint64_t)x[2] << 31 | (uint64_t)x[3] << 62; 407 | } else if (h > 32) { 408 | r |= (uint64_t)x[2] << 31; 409 | r |= -(r & ((uint64_t)1 << 61)); 410 | } else { 411 | r |= -(r & ((uint64_t)1 << 30)); 412 | } 413 | return r & ((uint64_t)(x[0] >> 31) - 1); 414 | } 415 | 416 | /* see cttk.h */ 417 | int64_t 418 | cttk_i31_to_s64_trunc(const uint32_t *x) 419 | { 420 | uint64_t r; 421 | 422 | r = cttk_i31_to_u64_trunc(x); 423 | return *(int64_t *)&r; 424 | } 425 | 426 | /* 427 | * Generic decoding routine. 428 | */ 429 | static void 430 | gendec(uint32_t *x, const void *src, size_t src_len, int be, int sig, int trunc) 431 | { 432 | uint32_t h, top, top2; 433 | const unsigned char *buf; 434 | size_t u, v, len; 435 | unsigned ssb, ssx, k, hk, extra_bits, extra_bits_len; 436 | cttk_bool in_range; 437 | 438 | x[0] &= 0x7FFFFFFF; 439 | h = x[0]; 440 | len = (h + 31) >> 5; 441 | memset(x + 1, 0, len * sizeof *x); 442 | if (src_len == 0) { 443 | if (sig) { 444 | x[0] |= 0x80000000; 445 | } 446 | return; 447 | } 448 | buf = src; 449 | hk = top_index(h); 450 | 451 | /* 452 | * 'ssb' is the value used for bytes beyond the source buffer. 453 | */ 454 | if (sig) { 455 | if (be) { 456 | ssb = -(unsigned)(buf[0] >> 7) & 0xFF; 457 | } else { 458 | ssb = -(unsigned)(buf[src_len - 1] >> 7) & 0xFF; 459 | } 460 | } else { 461 | ssb = 0; 462 | } 463 | 464 | /* 465 | * u:k points to the next bits to fill in x (u is word index, k 466 | * is bit index). 467 | * v is source byte index (counting from 0 for least significant). 468 | */ 469 | u = 0; 470 | k = 0; 471 | v = 0; 472 | 473 | /* 474 | * in_range is set to false if the value turns out to be out of 475 | * range (this is ignored if truncating). ssx is set to 0x00 or 476 | * 0xFF when the sign bit of x is reached. 477 | */ 478 | in_range = cttk_true; 479 | ssx = 0; 480 | 481 | /* 482 | * extra_bits / extra_bits_len will be set if there are extra bits 483 | * that must be checked against the final value sign. 484 | */ 485 | extra_bits = 0; 486 | extra_bits_len = 0; 487 | 488 | while (u < len || v < src_len) { 489 | unsigned b; 490 | 491 | /* 492 | * Get next byte of input in b. 493 | */ 494 | if (v < src_len) { 495 | b = be ? buf[src_len - 1 - v] : buf[v]; 496 | } else { 497 | b = ssb; 498 | } 499 | v ++; 500 | 501 | if (u < len) { 502 | if (k <= 23) { 503 | x[1 + u] |= (uint32_t)b << k; 504 | } else { 505 | /* 506 | * If we get beyond the last word boundary 507 | * then we may have some extra bits which 508 | * will have to be checked against the 509 | * value sign. 510 | */ 511 | x[1 + u] |= ((uint32_t)b << k) & 0x7FFFFFFF; 512 | if ((u + 1) < len) { 513 | x[2 + u] |= (uint32_t)b >> (31 - k); 514 | } else { 515 | extra_bits = (uint32_t)b >> (31 - k); 516 | extra_bits_len = k - 23; 517 | } 518 | } 519 | 520 | k += 8; 521 | if (k >= 31) { 522 | k -= 31; 523 | u ++; 524 | if (u == len) { 525 | ssx = -(unsigned)((x[len] >> hk) & 1) 526 | & 0xFF; 527 | } 528 | } 529 | } else { 530 | /* 531 | * If all words are filled, then we merely check 532 | * that extra bytes have a value compatible with 533 | * the range. 534 | */ 535 | in_range = cttk_and(in_range, cttk_u32_eq(b, ssx)); 536 | } 537 | } 538 | 539 | /* 540 | * We reach this point only when we filled all value words, and 541 | * read all source bytes. ssx has been set. We still need to do 542 | * some cleanup actions: 543 | * 544 | * - If truncating, then there may be some extra bits in the top 545 | * word that must be replaced with a sign extension. 546 | * 547 | * - If not truncating, then we must check that the extra bits 548 | * in the top word, and also the "extra bits" (if applicable), 549 | * have the proper value. Moreover, if source is unsigned, then 550 | * we must also check that we got a positive value. 551 | */ 552 | top = x[len]; 553 | top2 = signext(top, hk + 1) & 0x7FFFFFFF; 554 | if (trunc) { 555 | x[len] = top2; 556 | } else { 557 | in_range = cttk_and(in_range, cttk_u32_eq(top, top2)); 558 | if (extra_bits_len > 0) { 559 | in_range = cttk_and(in_range, cttk_u32_eq(extra_bits, 560 | ssx >> (8 - extra_bits_len))); 561 | } 562 | if (!sig) { 563 | in_range = cttk_and(in_range, cttk_u32_eq0(ssx)); 564 | } 565 | x[0] |= cttk_not(in_range).v << 31; 566 | } 567 | } 568 | 569 | /* 570 | * Generic encoding routine. 571 | */ 572 | static void 573 | genenc(void *dst, size_t dst_len, const uint32_t *x, int be) 574 | { 575 | unsigned char *buf; 576 | uint32_t h, acc, ssx; 577 | unsigned mask, acc_len; 578 | size_t u, len, v; 579 | 580 | h = x[0]; 581 | mask = (h >> 31) - 1; 582 | h &= 0x7FFFFFFF; 583 | len = (h + 31) >> 5; 584 | 585 | ssx = -(uint32_t)((x[len] >> top_index(h)) & 1) >> 1; 586 | acc = x[1]; 587 | acc_len = 31; 588 | u = 1; 589 | buf = dst; 590 | for (v = 0; v < dst_len; v ++) { 591 | unsigned b; 592 | 593 | if (acc_len >= 8) { 594 | b = acc & 0xFF; 595 | acc >>= 8; 596 | acc_len -= 8; 597 | } else { 598 | b = acc; 599 | if (u < len) { 600 | acc = x[1 + u]; 601 | u ++; 602 | } else { 603 | acc = ssx; 604 | } 605 | b |= acc << acc_len; 606 | acc >>= (8 - acc_len); 607 | acc_len += 23; 608 | } 609 | b &= mask; 610 | if (be) { 611 | buf[dst_len - 1 - v] = b; 612 | } else { 613 | buf[v] = b; 614 | } 615 | } 616 | } 617 | 618 | /* see cttk.h */ 619 | void 620 | cttk_i31_decbe_signed(uint32_t *x, const void *src, size_t len) 621 | { 622 | gendec(x, src, len, 1, 1, 0); 623 | } 624 | 625 | /* see cttk.h */ 626 | void 627 | cttk_i31_decbe_unsigned(uint32_t *x, const void *src, size_t len) 628 | { 629 | gendec(x, src, len, 1, 0, 0); 630 | } 631 | 632 | /* see cttk.h */ 633 | void 634 | cttk_i31_decbe_signed_trunc(uint32_t *x, const void *src, size_t len) 635 | { 636 | gendec(x, src, len, 1, 1, 1); 637 | } 638 | 639 | /* see cttk.h */ 640 | void 641 | cttk_i31_decbe_unsigned_trunc(uint32_t *x, const void *src, size_t len) 642 | { 643 | gendec(x, src, len, 1, 0, 1); 644 | } 645 | 646 | /* see cttk.h */ 647 | void 648 | cttk_i31_decle_signed(uint32_t *x, const void *src, size_t len) 649 | { 650 | gendec(x, src, len, 0, 1, 0); 651 | } 652 | 653 | /* see cttk.h */ 654 | void 655 | cttk_i31_decle_unsigned(uint32_t *x, const void *src, size_t len) 656 | { 657 | gendec(x, src, len, 0, 0, 0); 658 | } 659 | 660 | /* see cttk.h */ 661 | void 662 | cttk_i31_decle_signed_trunc(uint32_t *x, const void *src, size_t len) 663 | { 664 | gendec(x, src, len, 0, 1, 1); 665 | } 666 | 667 | /* see cttk.h */ 668 | void 669 | cttk_i31_decle_unsigned_trunc(uint32_t *x, const void *src, size_t len) 670 | { 671 | gendec(x, src, len, 0, 0, 1); 672 | } 673 | 674 | /* see cttk.h */ 675 | void 676 | cttk_i31_encbe(void *dst, size_t len, const uint32_t *x) 677 | { 678 | genenc(dst, len, x, 1); 679 | } 680 | 681 | /* see cttk.h */ 682 | void 683 | cttk_i31_encle(void *dst, size_t len, const uint32_t *x) 684 | { 685 | genenc(dst, len, x, 0); 686 | } 687 | 688 | /* 689 | * Compare x with zero. This function ignores the NaN flag. 690 | */ 691 | static cttk_bool 692 | val_eq0(const uint32_t *x) 693 | { 694 | uint32_t h, r; 695 | size_t len, u; 696 | 697 | h = x[0] & 0x7FFFFFFF; 698 | len = (h + 31) >> 5; 699 | r = 0; 700 | for (u = 0; u < len; u ++) { 701 | r |= x[u + 1]; 702 | } 703 | return cttk_u32_eq0(r); 704 | } 705 | 706 | /* 707 | * Test whether x is lower than zero. This function ignores the NaN 708 | * flag. Since it only grabs the sign bit, it is efficient even for 709 | * large integers. 710 | */ 711 | static cttk_bool 712 | val_lt0(const uint32_t *x) 713 | { 714 | uint32_t h; 715 | size_t len; 716 | 717 | h = x[0] & 0x7FFFFFFF; 718 | len = (h + 31) >> 5; 719 | return cttk_bool_of_u32((x[len] >> 30) & 1); 720 | } 721 | 722 | /* 723 | * Get actual bitlength, i.e. minimal number of bits to hold the value, 724 | * excluding the sign bit (hence, -1 has bitlength 0). This function 725 | * ignores the NaN flag. 726 | */ 727 | static uint32_t 728 | real_bitlength(const uint32_t *x) 729 | { 730 | uint32_t h, mx, t, g; 731 | size_t len, u; 732 | unsigned k; 733 | 734 | h = x[0] & 0x7FFFFFFF; 735 | len = (h + 31) >> 5; 736 | k = top_index(h); 737 | mx = -(uint32_t)((x[len] >> k) & 1) >> 1; 738 | 739 | /* 740 | * mx is an all-zero or all-one pattern (31 bits), depending on 741 | * sign bit value. We XOR it with the words, to normalize on the 742 | * positive case. We look for the index (g) and value (t) of the 743 | * topmost non-zero word. 744 | */ 745 | t = x[1]; 746 | g = 0; 747 | for (u = 1; u < len; u ++) { 748 | uint32_t w; 749 | cttk_bool nz; 750 | 751 | w = x[u + 1] ^ mx; 752 | nz = cttk_u32_neq0(w); 753 | t = cttk_u32_mux(nz, w, t); 754 | g = cttk_u32_mux(nz, (uint32_t)u, g); 755 | } 756 | 757 | return cttk_u32_bitlength(t) + (g << 5) - g; 758 | } 759 | 760 | /* see cttk.h */ 761 | uint32_t 762 | cttk_i31_to_u32(const uint32_t *x) 763 | { 764 | uint32_t r; 765 | 766 | r = cttk_i31_to_u32_trunc(x); 767 | r &= -cttk_u32_lt(real_bitlength(x), 33).v; 768 | r &= val_lt0(x).v - 1; 769 | return r; 770 | } 771 | 772 | /* see cttk.h */ 773 | int32_t 774 | cttk_i31_to_s32(const uint32_t *x) 775 | { 776 | uint32_t r; 777 | 778 | r = cttk_i31_to_u32_trunc(x); 779 | r &= -cttk_u32_lt(real_bitlength(x), 32).v; 780 | return *(int32_t *)&r; 781 | } 782 | 783 | /* see cttk.h */ 784 | uint64_t 785 | cttk_i31_to_u64(const uint32_t *x) 786 | { 787 | uint64_t r; 788 | 789 | r = cttk_i31_to_u64_trunc(x); 790 | r &= -(uint64_t)cttk_u32_lt(real_bitlength(x), 65).v; 791 | r &= (uint64_t)val_lt0(x).v - 1; 792 | return r; 793 | } 794 | 795 | /* see cttk.h */ 796 | int64_t 797 | cttk_i31_to_s64(const uint32_t *x) 798 | { 799 | uint64_t r; 800 | 801 | r = cttk_i31_to_u64_trunc(x); 802 | r &= -(uint64_t)cttk_u64_lt(real_bitlength(x), 64).v; 803 | return *(int64_t *)&r; 804 | } 805 | 806 | /* see cttk.h */ 807 | cttk_bool 808 | cttk_i31_eq0(const uint32_t *x) 809 | { 810 | return cttk_and(val_eq0(x), cttk_not(cttk_i31_isnan(x))); 811 | } 812 | 813 | /* see cttk.h */ 814 | cttk_bool 815 | cttk_i31_neq0(const uint32_t *x) 816 | { 817 | return cttk_not(cttk_or(val_eq0(x), cttk_i31_isnan(x))); 818 | } 819 | 820 | /* see cttk.h */ 821 | cttk_bool 822 | cttk_i31_gt0(const uint32_t *x) 823 | { 824 | return cttk_not(cttk_or(cttk_or(val_eq0(x), val_lt0(x)), 825 | cttk_i31_isnan(x))); 826 | } 827 | 828 | /* see cttk.h */ 829 | cttk_bool 830 | cttk_i31_lt0(const uint32_t *x) 831 | { 832 | return cttk_and(val_lt0(x), cttk_not(cttk_i31_isnan(x))); 833 | } 834 | 835 | /* see cttk.h */ 836 | cttk_bool 837 | cttk_i31_geq0(const uint32_t *x) 838 | { 839 | return cttk_not(cttk_or(val_lt0(x), cttk_i31_isnan(x))); 840 | } 841 | 842 | /* see cttk.h */ 843 | cttk_bool 844 | cttk_i31_leq0(const uint32_t *x) 845 | { 846 | return cttk_and(cttk_or(val_eq0(x), val_lt0(x)), 847 | cttk_not(cttk_i31_isnan(x))); 848 | } 849 | 850 | /* 851 | * Test two integers for NaN. This function returns true is either or 852 | * both are NaN. 853 | */ 854 | static inline cttk_bool 855 | tst_nan2(const uint32_t *x, const uint32_t *y) 856 | { 857 | return cttk_bool_of_u32((x[0] | y[0]) >> 31); 858 | } 859 | 860 | /* 861 | * Compare integers; this function assumes that both operands have the 862 | * same size. The common length (in words) is provided. The NaN flag 863 | * of each value is ignored. 864 | */ 865 | static cttk_bool 866 | val_eq(const uint32_t *x, const uint32_t *y) 867 | { 868 | size_t u, len; 869 | uint32_t r; 870 | 871 | len = ((x[0] & 0x7FFFFFFF) + 31) >> 5; 872 | r = 0; 873 | for (u = 0; u < len; u ++) { 874 | r |= x[1 + u] ^ y[1 + u]; 875 | } 876 | return cttk_u32_eq0(r); 877 | } 878 | 879 | /* 880 | * Compare integers; this function assumes that both operands have the 881 | * same size. The common length (in words) is provided. The header word 882 | * of each value is ignored. 883 | */ 884 | static cttk_bool 885 | val_lt(const uint32_t *x, const uint32_t *y) 886 | { 887 | size_t u, len; 888 | uint32_t cc; 889 | 890 | len = ((x[0] & 0x7FFFFFFF) + 31) >> 5; 891 | cc = 0; 892 | for (u = 0; u < len; u ++) { 893 | uint32_t wx, wy, wz; 894 | 895 | wx = x[u + 1]; 896 | wy = y[u + 1]; 897 | wz = wx - wy - cc; 898 | cc = (wz >> 31); 899 | } 900 | 901 | /* 902 | * Mathematical sign of the result (r), depending on the operand 903 | * signs and carry value: 904 | * 905 | * x y cc r 906 | * 907 | * 0 0 0 0 908 | * 0 0 1 1 909 | * 0 1 0 not possible 910 | * 0 1 1 0 911 | * 1 0 0 1 912 | * 1 0 1 not possible 913 | * 1 1 0 0 914 | * 1 1 1 1 915 | * 916 | * Thus, the XOR of the sign bits of x and y, and of the carry, 917 | * yields the sign of the result. 918 | */ 919 | cc ^= (x[len] ^ y[len]) >> 30; 920 | return cttk_bool_of_u32(cc); 921 | } 922 | 923 | /* 924 | * Generic integer comparison. This function assumes that both operands 925 | * have the same size, and ignores the NaN flags. Returned value is 926 | * -1, 0 or 1, converted to uint32_t. 927 | */ 928 | static uint32_t 929 | val_cmp(const uint32_t *x, const uint32_t *y) 930 | { 931 | size_t u, len; 932 | uint32_t cc, t; 933 | 934 | len = ((x[0] & 0x7FFFFFFF) + 31) >> 5; 935 | cc = 0; 936 | t = 0; 937 | for (u = 0; u < len; u ++) { 938 | uint32_t wx, wy, wz; 939 | 940 | wx = x[u + 1]; 941 | wy = y[u + 1]; 942 | wz = wx - wy - cc; 943 | cc = (wz >> 31); 944 | t |= wz; 945 | } 946 | 947 | /* 948 | * See val_lt0() for details. 949 | */ 950 | cc ^= (x[len] ^ y[len]) >> 30; 951 | return cttk_u32_neq0(t).v | -cc; 952 | } 953 | 954 | /* see cttk.h */ 955 | cttk_bool 956 | cttk_i31_eq(const uint32_t *x, const uint32_t *y) 957 | { 958 | if ((uint32_t)((x[0] ^ y[0]) << 1) != 0) { 959 | return cttk_false; 960 | } 961 | return cttk_and(val_eq(x, y), cttk_not(tst_nan2(x, y))); 962 | } 963 | 964 | /* see cttk.h */ 965 | cttk_bool 966 | cttk_i31_neq(const uint32_t *x, const uint32_t *y) 967 | { 968 | if ((uint32_t)((x[0] ^ y[0]) << 1) != 0) { 969 | return cttk_false; 970 | } 971 | return cttk_not(cttk_or(val_eq(x, y), tst_nan2(x, y))); 972 | } 973 | 974 | /* see cttk.h */ 975 | cttk_bool 976 | cttk_i31_lt(const uint32_t *x, const uint32_t *y) 977 | { 978 | if ((uint32_t)((x[0] ^ y[0]) << 1) != 0) { 979 | return cttk_false; 980 | } 981 | return cttk_and(val_lt(x, y), cttk_not(tst_nan2(x, y))); 982 | } 983 | 984 | /* see cttk.h */ 985 | cttk_bool 986 | cttk_i31_leq(const uint32_t *x, const uint32_t *y) 987 | { 988 | if ((uint32_t)((x[0] ^ y[0]) << 1) != 0) { 989 | return cttk_false; 990 | } 991 | return cttk_not(cttk_or(val_lt(y, x), tst_nan2(x, y))); 992 | } 993 | 994 | /* see cttk.h */ 995 | cttk_bool 996 | cttk_i31_gt(const uint32_t *x, const uint32_t *y) 997 | { 998 | if ((uint32_t)((x[0] ^ y[0]) << 1) != 0) { 999 | return cttk_false; 1000 | } 1001 | return cttk_and(val_lt(y, x), cttk_not(tst_nan2(x, y))); 1002 | } 1003 | 1004 | /* see cttk.h */ 1005 | cttk_bool 1006 | cttk_i31_geq(const uint32_t *x, const uint32_t *y) 1007 | { 1008 | if ((uint32_t)((x[0] ^ y[0]) << 1) != 0) { 1009 | return cttk_false; 1010 | } 1011 | return cttk_not(cttk_or(val_lt(x, y), tst_nan2(x, y))); 1012 | } 1013 | 1014 | /* see cttk.h */ 1015 | int 1016 | cttk_i31_sign(const uint32_t *x) 1017 | { 1018 | uint32_t w; 1019 | 1020 | w = (val_eq0(x).v ^ (uint32_t)1) | -val_lt0(x).v; 1021 | w &= (x[0] >> 31) - 1; 1022 | return *(int32_t *)&w; 1023 | } 1024 | 1025 | /* see cttk.h */ 1026 | int32_t 1027 | cttk_i31_cmp(const uint32_t *x, const uint32_t *y) 1028 | { 1029 | uint32_t w; 1030 | 1031 | if ((uint32_t)((x[0] ^ y[0]) << 1) != 0) { 1032 | return 0; 1033 | } 1034 | w = val_cmp(x, y) & (uint32_t)(((x[0] | y[0]) >> 31) - 1); 1035 | return *(int32_t *)&w; 1036 | } 1037 | 1038 | /* see cttk.h */ 1039 | void 1040 | cttk_i31_copy(uint32_t *d, const uint32_t *s) 1041 | { 1042 | if (d != s) { 1043 | if ((uint32_t)((d[0] ^ s[0]) << 1) != 0) { 1044 | d[0] |= 0x80000000; 1045 | return; 1046 | } 1047 | memcpy(d, s, (((s[0] & 0x7FFFFFFF) + 63) >> 5) * sizeof *s); 1048 | } 1049 | } 1050 | 1051 | /* see cttk.h */ 1052 | void 1053 | cttk_i31_cond_copy(cttk_bool ctl, uint32_t *d, const uint32_t *s) 1054 | { 1055 | cttk_i31_mux(ctl, d, s, d); 1056 | } 1057 | 1058 | /* see cttk.h */ 1059 | void 1060 | cttk_i31_swap(uint32_t *a, uint32_t *b) 1061 | { 1062 | size_t u, len; 1063 | 1064 | if (a == b) { 1065 | return; 1066 | } 1067 | if ((uint32_t)((a[0] ^ b[0]) << 1) != 0) { 1068 | a[0] |= 0x80000000; 1069 | b[0] |= 0x80000000; 1070 | return; 1071 | } 1072 | len = ((a[0] & 0x7FFFFFFF) + 63) >> 5; 1073 | for (u = 0; u < len; u ++) { 1074 | uint32_t w; 1075 | 1076 | w = a[u]; 1077 | a[u] = b[u]; 1078 | b[u] = w; 1079 | } 1080 | } 1081 | 1082 | /* see cttk.h */ 1083 | void 1084 | cttk_i31_cond_swap(cttk_bool ctl, uint32_t *a, uint32_t *b) 1085 | { 1086 | size_t u, len; 1087 | 1088 | if (a == b) { 1089 | return; 1090 | } 1091 | if ((uint32_t)((a[0] ^ b[0]) << 1) != 0) { 1092 | a[0] |= 0x80000000; 1093 | b[0] |= 0x80000000; 1094 | return; 1095 | } 1096 | len = ((a[0] & 0x7FFFFFFF) + 63) >> 5; 1097 | for (u = 0; u < len; u ++) { 1098 | uint32_t wa, wb, wt; 1099 | 1100 | wa = a[u]; 1101 | wb = b[u]; 1102 | wt = (wa ^ wb) & -ctl.v; 1103 | a[u] = wa ^ wt; 1104 | b[u] = wb ^ wt; 1105 | } 1106 | } 1107 | 1108 | /* see cttk.h */ 1109 | void 1110 | cttk_i31_mux(cttk_bool ctl, uint32_t *d, const uint32_t *a, const uint32_t *b) 1111 | { 1112 | uint32_t h; 1113 | size_t u, len; 1114 | 1115 | h = d[0] & 0x7FFFFFFF; 1116 | if (h != (a[0] & 0x7FFFFFFF) || h != (b[0] & 0x7FFFFFFF)) { 1117 | d[0] |= 0x80000000; 1118 | return; 1119 | } 1120 | len = (h + 63) >> 5; 1121 | for (u = 0; u < len; u ++) { 1122 | d[u] = cttk_u32_mux(ctl, a[u], b[u]); 1123 | } 1124 | } 1125 | 1126 | /* see cttk.h */ 1127 | void 1128 | cttk_i31_add(uint32_t *d, const uint32_t *a, const uint32_t *b) 1129 | { 1130 | uint32_t h, cc, tt; 1131 | size_t len, u; 1132 | 1133 | /* 1134 | * Compare sizes. This needs not be constant-time, but take 1135 | * care to mask out the NaN bit (since that one may be secret). 1136 | */ 1137 | h = d[0] & 0x7FFFFFFF; 1138 | if (h != (a[0] & 0x7FFFFFFF) || h != (b[0] & 0x7FFFFFFF)) { 1139 | d[0] |= 0x80000000; 1140 | return; 1141 | } 1142 | len = (h + 31) >> 5; 1143 | 1144 | /* 1145 | * Since sizes are equal, we can simply OR together the header 1146 | * words, which will propagate any NaN. 1147 | */ 1148 | d[0] = a[0] | b[0]; 1149 | 1150 | /* 1151 | * Get the XOR of the top words of a[] and b[]. This must be 1152 | * done now because either could be used as recipient. 1153 | */ 1154 | tt = a[len] ^ b[len]; 1155 | 1156 | /* 1157 | * Compute addition. 1158 | */ 1159 | cc = 0; 1160 | for (u = 0; u < len; u ++) { 1161 | uint32_t wa, wb, wd; 1162 | 1163 | wa = a[u + 1]; 1164 | wb = b[u + 1]; 1165 | wd = wa + wb + cc; 1166 | d[u + 1] = wd & 0x7FFFFFFF; 1167 | cc = wd >> 31; 1168 | } 1169 | 1170 | /* 1171 | * Overflow/underflow: 1172 | * 1173 | * Since source values are signed, they extend to infinity 1174 | * with copies of their sign bit. Depending on the signs of 1175 | * a and b, we get the following sign for the result (r): 1176 | * 1177 | * a b cc r 1178 | * 1179 | * 0 0 0 0 1180 | * 0 0 1 not possible 1181 | * 0 1 0 1 1182 | * 0 1 1 0 1183 | * 1 0 0 1 1184 | * 1 0 1 0 1185 | * 1 1 0 not possible 1186 | * 1 1 1 1 1187 | * 1188 | * Note that some combinations are not possible: when adding two 1189 | * zeros, even with a carry of 1, you cannot obtain a carry; 1190 | * similarly, when adding two ones, you cannot not get a carry. 1191 | * This hinges on the fact that source values are signed, and 1192 | * the carry we observe is necessarily _after_ processing the 1193 | * addition on their top (sign) bits. 1194 | * 1195 | * Note that in all cases, r is the XOR of the sign bits of a 1196 | * and b, and of the carry. Result is an overflow or underflow 1197 | * if and only if the obtained sign bit of d does not match that 1198 | * value. 1199 | */ 1200 | d[0] |= (((tt ^ d[len]) >> top_index(h)) ^ cc) << 31; 1201 | } 1202 | 1203 | /* see cttk.h */ 1204 | void 1205 | cttk_i31_add_trunc(uint32_t *d, const uint32_t *a, const uint32_t *b) 1206 | { 1207 | uint32_t h, cc; 1208 | size_t len, u; 1209 | 1210 | /* 1211 | * Compare sizes. This needs not be constant-time, but take 1212 | * care to mask out the NaN bit (since that one may be secret). 1213 | */ 1214 | h = d[0] & 0x7FFFFFFF; 1215 | if (h != (a[0] & 0x7FFFFFFF) || h != (b[0] & 0x7FFFFFFF)) { 1216 | d[0] |= 0x80000000; 1217 | return; 1218 | } 1219 | len = (h + 31) >> 5; 1220 | 1221 | /* 1222 | * Since sizes are equal, we can simply OR together the header 1223 | * words, which will propagate any NaN. 1224 | */ 1225 | d[0] = a[0] | b[0]; 1226 | 1227 | /* 1228 | * Compute addition. 1229 | */ 1230 | cc = 0; 1231 | for (u = 0; u < len; u ++) { 1232 | uint32_t wa, wb, wd; 1233 | 1234 | wa = a[u + 1]; 1235 | wb = b[u + 1]; 1236 | wd = wa + wb + cc; 1237 | d[u + 1] = wd & 0x7FFFFFFF; 1238 | cc = wd >> 31; 1239 | } 1240 | 1241 | /* 1242 | * Apply truncation to the proper size. 1243 | */ 1244 | d[len] = signext(d[len], top_index(h) + 1) & 0x7FFFFFFF; 1245 | } 1246 | 1247 | /* see cttk.h */ 1248 | void 1249 | cttk_i31_sub(uint32_t *d, const uint32_t *a, const uint32_t *b) 1250 | { 1251 | uint32_t h, cc, tt; 1252 | size_t len, u; 1253 | 1254 | /* 1255 | * Compare sizes. This needs not be constant-time, but take 1256 | * care to mask out the NaN bit (since that one may be secret). 1257 | */ 1258 | h = d[0] & 0x7FFFFFFF; 1259 | if (h != (a[0] & 0x7FFFFFFF) || h != (b[0] & 0x7FFFFFFF)) { 1260 | d[0] |= 0x80000000; 1261 | return; 1262 | } 1263 | len = (h + 31) >> 5; 1264 | 1265 | /* 1266 | * Since sizes are equal, we can simply OR together the header 1267 | * words, which will propagate any NaN. 1268 | */ 1269 | d[0] = a[0] | b[0]; 1270 | 1271 | /* 1272 | * Get the XOR of the top words of a[] and b[]. This must be 1273 | * done now because either could be used as recipient. 1274 | */ 1275 | tt = a[len] ^ b[len]; 1276 | 1277 | /* 1278 | * Compute subtraction. 1279 | */ 1280 | cc = 0; 1281 | for (u = 0; u < len; u ++) { 1282 | uint32_t wa, wb, wd; 1283 | 1284 | wa = a[u + 1]; 1285 | wb = b[u + 1]; 1286 | wd = wa - wb - cc; 1287 | d[u + 1] = wd & 0x7FFFFFFF; 1288 | cc = wd >> 31; 1289 | } 1290 | 1291 | /* 1292 | * Overflow/underflow: 1293 | * 1294 | * a b cc r 1295 | * 1296 | * 0 0 0 0 1297 | * 0 0 1 1 1298 | * 0 1 0 not possible 1299 | * 0 1 1 0 1300 | * 1 0 0 1 1301 | * 1 0 1 not possible 1302 | * 1 1 0 0 1303 | * 1 1 1 1 1304 | * 1305 | * This yields the same expression as for addition: the 1306 | * mathematical sign of the result is the XOR of the sign bits 1307 | * of the source and the carry. 1308 | */ 1309 | d[0] |= (((tt ^ d[len]) >> top_index(h)) ^ cc) << 31; 1310 | } 1311 | 1312 | /* see cttk.h */ 1313 | void 1314 | cttk_i31_sub_trunc(uint32_t *d, const uint32_t *a, const uint32_t *b) 1315 | { 1316 | uint32_t h, cc; 1317 | size_t len, u; 1318 | 1319 | /* 1320 | * Compare sizes. This needs not be constant-time, but take 1321 | * care to mask out the NaN bit (since that one may be secret). 1322 | */ 1323 | h = d[0] & 0x7FFFFFFF; 1324 | if (h != (a[0] & 0x7FFFFFFF) || h != (b[0] & 0x7FFFFFFF)) { 1325 | d[0] |= 0x80000000; 1326 | return; 1327 | } 1328 | len = (h + 31) >> 5; 1329 | 1330 | /* 1331 | * Since sizes are equal, we can simply OR together the header 1332 | * words, which will propagate any NaN. 1333 | */ 1334 | d[0] = a[0] | b[0]; 1335 | 1336 | /* 1337 | * Compute subtraction. 1338 | */ 1339 | cc = 0; 1340 | for (u = 0; u < len; u ++) { 1341 | uint32_t wa, wb, wd; 1342 | 1343 | wa = a[u + 1]; 1344 | wb = b[u + 1]; 1345 | wd = wa - wb - cc; 1346 | d[u + 1] = wd & 0x7FFFFFFF; 1347 | cc = wd >> 31; 1348 | } 1349 | 1350 | /* 1351 | * Apply truncation to the proper size. 1352 | */ 1353 | d[len] = signext(d[len], top_index(h) + 1) & 0x7FFFFFFF; 1354 | } 1355 | 1356 | /* see cttk.h */ 1357 | void 1358 | cttk_i31_neg(uint32_t *d, const uint32_t *x) 1359 | { 1360 | uint32_t h, cc, tt; 1361 | size_t u, len; 1362 | 1363 | h = x[0] & 0x7FFFFFFF; 1364 | if ((uint32_t)((h ^ d[0]) << 1) != 0) { 1365 | d[0] |= 0x80000000; 1366 | return; 1367 | } 1368 | 1369 | d[0] = x[0]; 1370 | len = (h + 31) >> 5; 1371 | cc = 1; 1372 | tt = x[len]; 1373 | for (u = 0; u < len; u ++) { 1374 | uint32_t w; 1375 | 1376 | w = x[u + 1]; 1377 | w = ~w + cc; 1378 | d[u + 1] = w & 0x7FFFFFFF; 1379 | cc = (w >> 31) ^ 1; 1380 | } 1381 | 1382 | /* 1383 | * We get an overflow if the source operand is equal to the 1384 | * minimum value in the representable range. This is the 1385 | * only situation where the sign bit of the source and of 1386 | * the result are both 1. 1387 | */ 1388 | d[0] |= (uint32_t)(((d[len] & tt) >> top_index(h)) & 1) << 31; 1389 | } 1390 | 1391 | /* see cttk.h */ 1392 | void 1393 | cttk_i31_neg_trunc(uint32_t *d, const uint32_t *x) 1394 | { 1395 | uint32_t h, cc; 1396 | size_t u, len; 1397 | 1398 | h = x[0] & 0x7FFFFFFF; 1399 | if ((uint32_t)((h ^ d[0]) << 1) != 0) { 1400 | d[0] |= 0x80000000; 1401 | return; 1402 | } 1403 | 1404 | d[0] = x[0]; 1405 | len = (h + 31) >> 5; 1406 | cc = 1; 1407 | for (u = 0; u < len; u ++) { 1408 | uint32_t w; 1409 | 1410 | w = x[u + 1]; 1411 | w = ~w + cc; 1412 | d[u + 1] = w & 0x7FFFFFFF; 1413 | cc = (w >> 31) ^ 1; 1414 | } 1415 | d[len] = signext(d[len], top_index(h) + 1) & 0x7FFFFFFF; 1416 | } 1417 | 1418 | /* 1419 | * Generic multiplication routine. It computes a truncated multiplication, 1420 | * but returns true if and only if the truncation changed the value. This 1421 | * function: 1422 | * - ignores the NaN flag; 1423 | * - assumes that source and destination operands have the same size; 1424 | * - assumes that the destination array is distinct from the source arrays. 1425 | * 1426 | * TODO: use Karatsuba for large inputs. 1427 | */ 1428 | static cttk_bool 1429 | genmul_separate(uint32_t *d, const uint32_t *a, const uint32_t *b) 1430 | { 1431 | uint32_t h, ssa, ssb, ssd; 1432 | size_t u, v, len; 1433 | uint64_t cc; 1434 | cttk_bool only0, only1, opz; 1435 | 1436 | h = d[0] & 0x7FFFFFFF; 1437 | len = (h + 31) >> 5; 1438 | ssa = -(uint32_t)(a[len] >> 30) >> 1; 1439 | ssb = -(uint32_t)(b[len] >> 30) >> 1; 1440 | only0 = cttk_true; 1441 | only1 = cttk_true; 1442 | opz = cttk_or(cttk_i31_eq0(a), cttk_i31_eq0(b)); 1443 | 1444 | cc = 0; 1445 | for (u = 0; u < (len << 1); u ++) { 1446 | uint32_t wd; 1447 | uint64_t zd; 1448 | 1449 | zd = cc; 1450 | cc = 0; 1451 | for (v = 0; v <= u; v ++) { 1452 | uint32_t wa, wb; 1453 | uint64_t zr; 1454 | 1455 | wa = v < len ? a[1 + v] : ssa; 1456 | wb = (v + len) > u ? b[1 + u - v] : ssb; 1457 | zr = mulu32w(wa, wb); 1458 | zd += zr & 0x7FFFFFFF; 1459 | cc += zr >> 31; 1460 | } 1461 | cc += zd >> 31; 1462 | wd = (uint32_t)zd & 0x7FFFFFFF; 1463 | if (u < len) { 1464 | d[1 + u] = wd; 1465 | } else { 1466 | only0 = cttk_and(only0, cttk_u32_eq0(wd)); 1467 | only1 = cttk_and(only1, cttk_u32_eq0(wd ^ 0x7FFFFFFF)); 1468 | } 1469 | } 1470 | 1471 | /* 1472 | * We check that all upper bits have a value compatible with the 1473 | * expected result sign. 1474 | */ 1475 | ssd = ssa ^ ssb; 1476 | ssd &= (uint32_t)(opz.v - 1); 1477 | return cttk_and( 1478 | cttk_bool_of_u32(cttk_u32_mux( 1479 | cttk_bool_of_u32(ssd & 1), only1.v, only0.v)), 1480 | cttk_u32_eq0((d[len] ^ ssd) >> top_index(h))); 1481 | } 1482 | 1483 | /* 1484 | * Multiplication function with a stack-based temporary. Assumptions: 1485 | * 1486 | * - d is equal (same pointer value) to a or b or both; 1487 | * - a, b and d have the same size; 1488 | * - the common size does not exceed CTTK_MAX_INT_BUF bytes. 1489 | */ 1490 | static cttk_bool 1491 | genmul_stack(uint32_t *d, const uint32_t *a, const uint32_t *b) 1492 | { 1493 | uint32_t t[CTTK_MAX_INT_BUF / sizeof(uint32_t)]; 1494 | uint32_t h; 1495 | size_t len; 1496 | cttk_bool r; 1497 | 1498 | h = d[0] & 0x7FFFFFFF; 1499 | t[0] = h; 1500 | len = (h + 31) >> 5; 1501 | memset(t + 1, 0, len * sizeof t[0]); 1502 | r = genmul_separate(t, a, b); 1503 | memcpy(d + 1, t + 1, len * sizeof *d); 1504 | return r; 1505 | } 1506 | 1507 | static cttk_bool 1508 | genmul(uint32_t *d, const uint32_t *a, const uint32_t *b) 1509 | { 1510 | uint32_t h; 1511 | size_t blen; 1512 | 1513 | h = d[0] & 0x7FFFFFFF; 1514 | if (h != (a[0] & 0x7FFFFFFF) || h != (b[0] & 0x7FFFFFFF)) { 1515 | d[0] |= 0x80000000; 1516 | return cttk_false; 1517 | } 1518 | d[0] = a[0] | b[0]; 1519 | 1520 | if (d != a && d != b) { 1521 | return genmul_separate(d, a, b); 1522 | } 1523 | blen = ((h + 63) >> 5) * sizeof *d; 1524 | if (blen <= CTTK_MAX_INT_BUF) { 1525 | return genmul_stack(d, a, b); 1526 | } 1527 | #if !CTTK_NO_MALLOC 1528 | { 1529 | uint32_t *t; 1530 | 1531 | t = malloc(blen); 1532 | if (t != NULL) { 1533 | cttk_bool r; 1534 | size_t len; 1535 | 1536 | t[0] = h; 1537 | len = (h + 31) >> 5; 1538 | memset(t + 1, 0, len * sizeof *t); 1539 | r = genmul_separate(t, a, b); 1540 | memcpy(d + 1, t + 1, len * sizeof *t); 1541 | free(t); 1542 | return r; 1543 | } 1544 | } 1545 | #endif 1546 | d[0] |= 0x80000000; 1547 | return cttk_false; 1548 | } 1549 | 1550 | /* see cttk.h */ 1551 | void 1552 | cttk_i31_mul(uint32_t *d, const uint32_t *a, const uint32_t *b) 1553 | { 1554 | cttk_bool r; 1555 | 1556 | r = genmul(d, a, b); 1557 | d[0] |= (r.v ^ 1) << 31; 1558 | } 1559 | 1560 | /* see cttk.h */ 1561 | void 1562 | cttk_i31_mul_trunc(uint32_t *d, const uint32_t *a, const uint32_t *b) 1563 | { 1564 | uint32_t h; 1565 | size_t len; 1566 | 1567 | genmul(d, a, b); 1568 | h = d[0] & 0x7FFFFFFF; 1569 | len = (h + 31) >> 5; 1570 | d[len] = signext(d[len], top_index(h) + 1) & 0x7FFFFFFF; 1571 | } 1572 | 1573 | /* 1574 | * Generic left-shift function: 1575 | * 1576 | * - d and a must have been already verified to have the same size. 1577 | * - Shift count is n = nd*31+nm, with 0 <= nm < 31, and n fits on 32 bits. 1578 | * - If ctl is false, then the shift is not actually done. 1579 | * 1580 | * Returned value is false if the value overflows/underflows. 1581 | * 1582 | * nd and nm may leak. 1583 | */ 1584 | static cttk_bool 1585 | genlsh(uint32_t *d, const uint32_t *a, uint32_t nd, unsigned nm, cttk_bool ctl) 1586 | { 1587 | uint32_t n, h, hk, bl, ssa, tt; 1588 | size_t len, u; 1589 | cttk_bool r; 1590 | 1591 | d[0] = a[0]; 1592 | h = d[0] & 0x7FFFFFFF; 1593 | len = (h + 31) >> 5; 1594 | bl = h - (h >> 5); 1595 | n = 31 * nd + nm; 1596 | ssa = -(a[len] >> 30) & 0x7FFFFFFF; 1597 | 1598 | /* 1599 | * If the shift count is greater than or equal to the type size, 1600 | * then we can only get zero. This is an overflow/underflow if 1601 | * the source value is not 0. 1602 | */ 1603 | if (n >= bl) { 1604 | r = cttk_true; 1605 | for (u = 0; u < len; u ++) { 1606 | uint32_t wa; 1607 | 1608 | wa = a[1 + u]; 1609 | r = cttk_and(r, cttk_u32_eq0(wa)); 1610 | d[1 + u] = wa & (uint32_t)(ctl.v - 1); 1611 | } 1612 | return cttk_or(r, cttk_not(ctl)); 1613 | } 1614 | 1615 | /* 1616 | * We have: 1617 | * len * 31 >= bl 1618 | * n >= 31 * nd 1619 | * We reach that point only if n < bl, which implies nd < len. 1620 | */ 1621 | 1622 | /* 1623 | * Since source and destination may be the same array, we need 1624 | * to do the shift in high to low order. 1625 | */ 1626 | r = cttk_true; 1627 | for (u = len; u > len - nd; u --) { 1628 | r = cttk_and(r, cttk_u32_eq(ssa, a[u])); 1629 | } 1630 | if (nm == 0) { 1631 | for (u = len; u > nd; u --) { 1632 | d[u] = cttk_u32_mux(ctl, a[u - nd], a[u]); 1633 | } 1634 | } else { 1635 | r = cttk_and(r, 1636 | cttk_u32_eq0((a[len - nd] ^ ssa) >> (31 - nm))); 1637 | for (u = len; u > nd; u --) { 1638 | uint32_t wa, wd; 1639 | 1640 | wa = a[u - nd]; 1641 | wd = (wa << nm) & 0x7FFFFFFF; 1642 | if ((u - nd) > 1) { 1643 | wd |= a[u - nd - 1] >> (31 - nm); 1644 | } 1645 | d[u] = cttk_u32_mux(ctl, wd, a[u]); 1646 | } 1647 | } 1648 | for (u = nd; u > 0; u --) { 1649 | d[u] = a[u] & (ctl.v - 1); 1650 | } 1651 | 1652 | /* 1653 | * 'r' contains the overflow/underflow check for all the dropped 1654 | * bits, but we must still check the top bits in the high word 1655 | * are all equal to the expected sign (and we should also adjust 1656 | * them, for truncation support). 1657 | */ 1658 | hk = top_index(h); 1659 | tt = signext(d[len], hk + 1) & 0x7FFFFFFF; 1660 | r = cttk_and(r, cttk_u32_eq(d[len], tt)); 1661 | d[len] = tt; 1662 | r = cttk_and(r, cttk_u32_eq0((tt ^ ssa) >> hk)); 1663 | 1664 | /* 1665 | * We must also check that the final sign matches the source sign; 1666 | * otherwise, the checks ab 1667 | */ 1668 | return cttk_or(r, cttk_not(ctl)); 1669 | } 1670 | 1671 | /* 1672 | * Generic right-shift function: 1673 | * 1674 | * - d and a must have been already verified to have the same size. 1675 | * - Shift count is n = nd*31+nm, with 0 <= nm < 31, and n fits on 32 bits. 1676 | * - If ctl is false, then the shift is not actually done. 1677 | * 1678 | * nd and nm may leak. 1679 | */ 1680 | static void 1681 | genrsh(uint32_t *d, const uint32_t *a, uint32_t nd, unsigned nm, cttk_bool ctl) 1682 | { 1683 | uint32_t h, ssa, n, bl; 1684 | size_t u, len; 1685 | 1686 | d[0] = a[0]; 1687 | h = d[0] & 0x7FFFFFFF; 1688 | len = (h + 31) >> 5; 1689 | bl = h - (h >> 5); 1690 | n = 31 * nd + nm; 1691 | ssa = -(a[len] >> 30) & 0x7FFFFFFF; 1692 | 1693 | /* 1694 | * If right-shifting by at least bl-1 bits, then the result is 1695 | * either 0 or -1, depending on source sign. 1696 | */ 1697 | if ((n + 1) >= bl) { 1698 | for (u = 0; u < len; u ++) { 1699 | d[1 + u] = cttk_u32_mux(ctl, ssa, a[1 + u]); 1700 | } 1701 | return; 1702 | } 1703 | 1704 | /* 1705 | * We have: 1706 | * len * 31 >= bl 1707 | * n >= 31 * nd 1708 | * We reach that point only if n < bl, which implies nd < len. 1709 | */ 1710 | 1711 | if (nm == 0) { 1712 | for (u = 0; u < (len - nd); u ++) { 1713 | d[1 + u] = cttk_u32_mux(ctl, a[1 + u + nd], a[1 + u]); 1714 | } 1715 | } else { 1716 | for (u = 0; u < (len - nd - 1); u ++) { 1717 | uint32_t wa; 1718 | 1719 | wa = ((a[1 + u + nd] >> nm) 1720 | | (a[2 + u + nd] << (31 - nm))) & 0x7FFFFFFF; 1721 | d[1 + u] = cttk_u32_mux(ctl, wa, a[1 + u]); 1722 | } 1723 | d[len - nd] = cttk_u32_mux(ctl, 1724 | ((a[len] >> nm) | (ssa << (31 - nm))) & 0x7FFFFFFF, 1725 | a[len - nd]); 1726 | } 1727 | for (u = len - nd; u < len; u ++) { 1728 | d[1 + u] = cttk_u32_mux(ctl, ssa, a[1 + u]); 1729 | } 1730 | } 1731 | 1732 | /* 1733 | * Precomputed powers of two divided by 31 (quotient and remainder). 1734 | */ 1735 | static const uint32_t p2m31[] = { 1736 | ((uint32_t)1 << 0) / 31, ((uint32_t)1 << 0) % 31, 1737 | ((uint32_t)1 << 1) / 31, ((uint32_t)1 << 1) % 31, 1738 | ((uint32_t)1 << 2) / 31, ((uint32_t)1 << 2) % 31, 1739 | ((uint32_t)1 << 3) / 31, ((uint32_t)1 << 3) % 31, 1740 | ((uint32_t)1 << 4) / 31, ((uint32_t)1 << 4) % 31, 1741 | ((uint32_t)1 << 5) / 31, ((uint32_t)1 << 5) % 31, 1742 | ((uint32_t)1 << 6) / 31, ((uint32_t)1 << 6) % 31, 1743 | ((uint32_t)1 << 7) / 31, ((uint32_t)1 << 7) % 31, 1744 | ((uint32_t)1 << 8) / 31, ((uint32_t)1 << 8) % 31, 1745 | ((uint32_t)1 << 9) / 31, ((uint32_t)1 << 9) % 31, 1746 | ((uint32_t)1 << 10) / 31, ((uint32_t)1 << 10) % 31, 1747 | ((uint32_t)1 << 11) / 31, ((uint32_t)1 << 11) % 31, 1748 | ((uint32_t)1 << 12) / 31, ((uint32_t)1 << 12) % 31, 1749 | ((uint32_t)1 << 13) / 31, ((uint32_t)1 << 13) % 31, 1750 | ((uint32_t)1 << 14) / 31, ((uint32_t)1 << 14) % 31, 1751 | ((uint32_t)1 << 15) / 31, ((uint32_t)1 << 15) % 31, 1752 | ((uint32_t)1 << 16) / 31, ((uint32_t)1 << 16) % 31, 1753 | ((uint32_t)1 << 17) / 31, ((uint32_t)1 << 17) % 31, 1754 | ((uint32_t)1 << 18) / 31, ((uint32_t)1 << 18) % 31, 1755 | ((uint32_t)1 << 19) / 31, ((uint32_t)1 << 19) % 31, 1756 | ((uint32_t)1 << 20) / 31, ((uint32_t)1 << 20) % 31, 1757 | ((uint32_t)1 << 21) / 31, ((uint32_t)1 << 21) % 31, 1758 | ((uint32_t)1 << 22) / 31, ((uint32_t)1 << 22) % 31, 1759 | ((uint32_t)1 << 23) / 31, ((uint32_t)1 << 23) % 31, 1760 | ((uint32_t)1 << 24) / 31, ((uint32_t)1 << 24) % 31, 1761 | ((uint32_t)1 << 25) / 31, ((uint32_t)1 << 25) % 31, 1762 | ((uint32_t)1 << 26) / 31, ((uint32_t)1 << 26) % 31, 1763 | ((uint32_t)1 << 27) / 31, ((uint32_t)1 << 27) % 31, 1764 | ((uint32_t)1 << 28) / 31, ((uint32_t)1 << 28) % 31, 1765 | ((uint32_t)1 << 29) / 31, ((uint32_t)1 << 29) % 31, 1766 | ((uint32_t)1 << 30) / 31, ((uint32_t)1 << 30) % 31, 1767 | ((uint32_t)1 << 31) / 31, ((uint32_t)1 << 31) % 31, 1768 | }; 1769 | 1770 | /* see cttk.h */ 1771 | void 1772 | cttk_i31_lsh(uint32_t *d, const uint32_t *a, uint32_t n) 1773 | { 1774 | cttk_bool r; 1775 | 1776 | if (((d[0] ^ a[0]) << 1) != 0) { 1777 | d[0] |= 0x80000000; 1778 | return; 1779 | } 1780 | r = genlsh(d, a, n / 31, n % 31, cttk_true); 1781 | d[0] |= (r.v ^ 1) << 31; 1782 | } 1783 | 1784 | /* see cttk.h */ 1785 | void 1786 | cttk_i31_lsh_prot(uint32_t *d, const uint32_t *a, uint32_t n) 1787 | { 1788 | int i; 1789 | 1790 | if (((d[0] ^ a[0]) << 1) != 0) { 1791 | d[0] |= 0x80000000; 1792 | return; 1793 | } 1794 | for (i = 0; i < 32; i ++) { 1795 | cttk_bool r; 1796 | 1797 | r = genlsh(d, a, p2m31[i << 1], p2m31[(i << 1) + 1], 1798 | cttk_u32_neq0(n & ((uint32_t)1 << i))); 1799 | d[0] |= (r.v ^ 1) << 31; 1800 | a = d; 1801 | } 1802 | } 1803 | 1804 | /* see cttk.h */ 1805 | void 1806 | cttk_i31_lsh_trunc(uint32_t *d, const uint32_t *a, uint32_t n) 1807 | { 1808 | if (((d[0] ^ a[0]) << 1) != 0) { 1809 | d[0] |= 0x80000000; 1810 | return; 1811 | } 1812 | genlsh(d, a, n / 31, n % 31, cttk_true); 1813 | } 1814 | 1815 | /* see cttk.h */ 1816 | void 1817 | cttk_i31_lsh_trunc_prot(uint32_t *d, const uint32_t *a, uint32_t n) 1818 | { 1819 | int i; 1820 | 1821 | if (((d[0] ^ a[0]) << 1) != 0) { 1822 | d[0] |= 0x80000000; 1823 | return; 1824 | } 1825 | for (i = 0; i < 32; i ++) { 1826 | genlsh(d, a, p2m31[i << 1], p2m31[(i << 1) + 1], 1827 | cttk_u32_neq0(n & ((uint32_t)1 << i))); 1828 | a = d; 1829 | } 1830 | } 1831 | 1832 | /* see cttk.h */ 1833 | void 1834 | cttk_i31_rsh(uint32_t *d, const uint32_t *a, uint32_t n) 1835 | { 1836 | if (((d[0] ^ a[0]) << 1) != 0) { 1837 | d[0] |= 0x80000000; 1838 | return; 1839 | } 1840 | genrsh(d, a, n / 31, n % 31, cttk_true); 1841 | } 1842 | 1843 | /* see cttk.h */ 1844 | void 1845 | cttk_i31_rsh_prot(uint32_t *d, const uint32_t *a, uint32_t n) 1846 | { 1847 | int i; 1848 | 1849 | if (((d[0] ^ a[0]) << 1) != 0) { 1850 | d[0] |= 0x80000000; 1851 | return; 1852 | } 1853 | for (i = 0; i < 32; i ++) { 1854 | genrsh(d, a, p2m31[i << 1], p2m31[(i << 1) + 1], 1855 | cttk_u32_neq0(n & ((uint32_t)1 << i))); 1856 | a = d; 1857 | } 1858 | } 1859 | 1860 | /* 1861 | * Internal division routine: 1862 | * 1863 | * - r is non-NULL. 1864 | * - q, r, t1 and t2 are distinct from each other. Only q may be NULL. 1865 | * - t1 and t2 are distinct from a and b. 1866 | * - All non-NULL arrays have the same size. 1867 | * 1868 | * Note that q and r may be aliases on a or b. 1869 | */ 1870 | static void 1871 | gendiv_inner(uint32_t *q, uint32_t *r, const uint32_t *a, 1872 | const uint32_t *b, uint32_t *t1, uint32_t *t2, int mod) 1873 | { 1874 | uint32_t h, n, hk, sa, sb; 1875 | size_t ud, len, u; 1876 | unsigned um; 1877 | cttk_bool a_isnan, a_isminv, b_isnan, b_isminv, b_iszero, b_ismone; 1878 | cttk_bool both_nan, half_nan; 1879 | 1880 | h = b[0] & 0x7FFFFFFF; 1881 | hk = top_index(h); 1882 | n = h - (h >> 5); 1883 | ud = h >> 5; 1884 | um = h & 31; 1885 | len = (h + 31) >> 5; 1886 | 1887 | /* 1888 | * We use absolute values, and then adjust signs. 1889 | * Special cases are the following: 1890 | * 1891 | * - If a is NaN and/or b is NaN, then q and r are set to NaN. 1892 | * - If b is zero, then q and r are set to NaN. 1893 | * - If a and/or b is MinValue, then the corresponding absolute 1894 | * value cannot be computed. Instead, we have to perform the 1895 | * following adjustments: 1896 | * 1897 | * If a == MinValue and b < 0, subtract b from a, and add 1 1898 | * to q before adjusting its sign. 1899 | * 1900 | * If a == MinValue and b > 0, add b to a, and add 1 to q 1901 | * before adjusting its sign. 1902 | * 1903 | * If b == MinValue and a == MinValue, then set q to 1 and 1904 | * r to 0. 1905 | * 1906 | * If b == MinValue and a != MinValue, then set q to 0 and 1907 | * r to a. 1908 | * 1909 | * The two first rules may be merged into the following: 1910 | * 1911 | * If a == MinValue, add |b| to a, and add 1 to q before 1912 | * adjusting its sign. 1913 | */ 1914 | 1915 | /* 1916 | * If a or b is NaN, or b is zero, then both q and r will be NaN. 1917 | * If a is MinValue and b is -1, then q = NaN and r = 0. 1918 | * We obtain the relevant values here: 1919 | * a_isnan a is NaN 1920 | * b_isnan b is NaN 1921 | * a_isminv a == MinValue 1922 | * b_isminv b == MinValue 1923 | * b_iszero b == 0 1924 | * b_ismone b == -1 1925 | */ 1926 | a_isnan = cttk_i31_isnan(a); 1927 | b_isnan = cttk_i31_isnan(b); 1928 | a_isminv = cttk_true; 1929 | b_isminv = cttk_true; 1930 | b_iszero = cttk_true; 1931 | b_ismone = cttk_true; 1932 | for (u = 0; (u + 1) < len; u ++) { 1933 | a_isminv = cttk_and(a_isminv, cttk_u32_eq0(a[1 + u])); 1934 | b_isminv = cttk_and(b_isminv, cttk_u32_eq0(b[1 + u])); 1935 | b_iszero = cttk_and(b_iszero, cttk_u32_eq0(b[1 + u])); 1936 | b_ismone = cttk_and(b_iszero, 1937 | cttk_u32_eq(b[1 + u], 0x7FFFFFFF)); 1938 | } 1939 | a_isminv = cttk_and(a_isminv, 1940 | cttk_u32_eq(a[len], ((uint32_t)-1 << hk) & 0x7FFFFFFF)); 1941 | b_isminv = cttk_and(b_isminv, 1942 | cttk_u32_eq(b[len], ((uint32_t)-1 << hk) & 0x7FFFFFFF)); 1943 | b_iszero = cttk_and(b_iszero, cttk_u32_eq0(b[len])); 1944 | b_ismone = cttk_and(b_ismone, cttk_u32_eq(b[len], 0x7FFFFFFF)); 1945 | 1946 | /* 1947 | * Get signs. 1948 | */ 1949 | sa = a[len] >> 30; 1950 | sb = b[len] >> 30; 1951 | 1952 | /* 1953 | * Compute |b| into t2. 1954 | */ 1955 | cttk_i31_neg(t2, b); 1956 | cttk_i31_cond_copy(cttk_u32_eq0(sb), t2, b); 1957 | 1958 | /* 1959 | * Set r to |a| or |a+|b||. t1 is free at that point. r may be 1960 | * aliased on a or b, but not on t1. 1961 | */ 1962 | cttk_i31_add(t1, a, t2); 1963 | cttk_i31_cond_copy(cttk_not(a_isminv), t1, a); 1964 | cttk_i31_neg(r, t1); 1965 | cttk_i31_cond_copy(cttk_not(cttk_bool_of_u32(t1[len] >> 30)), r, t1); 1966 | 1967 | /* 1968 | * Now r is set, and |b|. We "forget" about the true b, and instead 1969 | * use |b|. 1970 | */ 1971 | b = t2; 1972 | 1973 | /* 1974 | * Set q to 0 (if defined). 1975 | */ 1976 | if (q != NULL) { 1977 | q[0] &= 0x7FFFFFFF; 1978 | memset(q + 1, 0, ((h + 31) >> 5) * sizeof *q); 1979 | } 1980 | 1981 | /* 1982 | * Compute the division on the positive values. 1983 | */ 1984 | while (n -- > 0) { 1985 | cttk_bool e; 1986 | 1987 | /* 1988 | * The shift on b may yield a NaN, but in that case, the 1989 | * comparison will be false, and the cond_copy will put 1990 | * back the non-NaN value of r. 1991 | */ 1992 | cttk_i31_lsh(t1, b, n); 1993 | e = cttk_i31_leq(t1, r); 1994 | cttk_i31_sub(t1, r, t1); 1995 | cttk_i31_cond_copy(e, r, t1); 1996 | if (q != NULL) { 1997 | if (um == 0) { 1998 | um = 30; 1999 | ud --; 2000 | } else { 2001 | um --; 2002 | } 2003 | q[1 + ud] |= e.v << um; 2004 | } 2005 | } 2006 | 2007 | /* 2008 | * Adjust values and signs. t1 is free. 2009 | */ 2010 | if (q != NULL) { 2011 | int32_t p; 2012 | 2013 | /* 2014 | * If b == MinValue, then we must set q to 0; if 2015 | * a == MinValue too, we will add 1 afterwards. 2016 | */ 2017 | cttk_i31_set_u32_trunc(t1, 0); 2018 | cttk_i31_cond_copy(b_isminv, q, t1); 2019 | 2020 | /* 2021 | * We adjust the sign of q: it is negative if the 2022 | * signs of a and b differ. 2023 | */ 2024 | cttk_i31_neg(t1, q); 2025 | cttk_i31_cond_copy(cttk_bool_of_u32(sa ^ sb), q, t1); 2026 | 2027 | /* 2028 | * If a == MinValue, then there is a +1 or -1 to add. 2029 | * Normally we would do the +1 before adjusting the 2030 | * sign of q, but there is an edge case where the +1 2031 | * would set the value to MaxValue+1 (i.e. NaN), 2032 | * whereas setting the sign first, then subtracting 1, 2033 | * yields MinValue (which is correct and not NaN). 2034 | */ 2035 | p = cttk_bool_to_int(a_isminv); 2036 | cttk_i31_set_s32(t1, 2037 | cttk_s32_mux(cttk_bool_of_u32(sa ^ sb), -p, p)); 2038 | cttk_i31_add(q, q, t1); 2039 | } 2040 | cttk_i31_neg(t1, r); 2041 | cttk_i31_cond_copy(cttk_bool_of_u32(sa), r, t1); 2042 | 2043 | /* 2044 | * Handle the special cases for b == MinValue. In that case, 2045 | * when we computed |b|, we got a NaN, and all checks in the 2046 | * loop were false. Thus, if a != MinValue, r contains a copy 2047 | * of a at this point (which is correct) and we just have to 2048 | * set the quotient to 0. 2049 | */ 2050 | cttk_i31_set_u32_trunc(t1, 0); 2051 | if (q != NULL) { 2052 | cttk_i31_cond_copy( 2053 | cttk_and(b_isminv, cttk_not(a_isminv)), q, t1); 2054 | } 2055 | cttk_i31_cond_copy(cttk_and(b_isminv, a_isminv), r, t1); 2056 | if (q != NULL) { 2057 | cttk_i31_set_u32(t1, 1); 2058 | cttk_i31_cond_copy(cttk_and(b_isminv, a_isminv), q, t1); 2059 | } 2060 | 2061 | /* 2062 | * Apply NaN conditions. 2063 | */ 2064 | both_nan = cttk_or(cttk_or(a_isnan, b_isnan), b_iszero); 2065 | half_nan = cttk_and(a_isminv, b_ismone); 2066 | if (q != NULL) { 2067 | q[0] |= cttk_or(both_nan, half_nan).v << 31; 2068 | } 2069 | r[0] |= both_nan.v << 31; 2070 | cttk_i31_set_u32_trunc(t1, 0); 2071 | cttk_i31_cond_copy(half_nan, r, t1); 2072 | 2073 | /* 2074 | * Extra step if doing modular reduction: 2075 | * - If r >= 0, it is already fine. 2076 | * - If r < 0 and b < 0, then we must subtract b. 2077 | * - If r < 0 and b > 0, then we must add b. 2078 | * 2079 | * Since |r| < |b|, then we have the following properties: 2080 | * - If the generic division hit a NaN, then the result must 2081 | * be a NaN as well. 2082 | * - If r and b are both non-NaN, then the extra operation 2083 | * cannot overflow or underflow. 2084 | * 2085 | * We may not have b anymore at that point, though (since r 2086 | * might be aliased to b). We have |b| in t2 (and we set the 'b' 2087 | * pointer to t2). We can add |b| conditionally to r being 2088 | * negative. However, |b| might be a NaN if b == MinValue; we 2089 | * must isolate that case. 2090 | */ 2091 | if (mod) { 2092 | uint32_t sr; 2093 | 2094 | sr = r[len] >> 30; 2095 | cttk_i31_add(t1, r, b); 2096 | cttk_i31_cond_copy(cttk_and(cttk_bool_of_u32(sr), 2097 | cttk_not(b_isminv)), r, t1); 2098 | 2099 | /* 2100 | * When b == MinValue, we want to subtract MinValue from 2101 | * r, which is equivalent to flipping the sign bit. 2102 | */ 2103 | r[len] ^= ((-(sr & b_isminv.v) << hk) & 0x7FFFFFFF); 2104 | } 2105 | } 2106 | 2107 | static void 2108 | gendiv_stack3(uint32_t *q, const uint32_t *a, const uint32_t *b, int mod) 2109 | { 2110 | uint32_t tr[CTTK_MAX_INT_BUF / (3 * sizeof(uint32_t))]; 2111 | uint32_t t1[CTTK_MAX_INT_BUF / (3 * sizeof(uint32_t))]; 2112 | uint32_t t2[CTTK_MAX_INT_BUF / (3 * sizeof(uint32_t))]; 2113 | 2114 | memset(tr, 0, sizeof tr); 2115 | memset(t1, 0, sizeof t1); 2116 | memset(t2, 0, sizeof t2); 2117 | tr[0] = t1[0] = t2[0] = a[0]; 2118 | gendiv_inner(q, tr, a, b, t1, t2, mod); 2119 | } 2120 | 2121 | static void 2122 | gendiv_stack2(uint32_t *q, uint32_t *r, 2123 | const uint32_t *a, const uint32_t *b, int mod) 2124 | { 2125 | uint32_t t1[CTTK_MAX_INT_BUF / (3 * sizeof(uint32_t))]; 2126 | uint32_t t2[CTTK_MAX_INT_BUF / (3 * sizeof(uint32_t))]; 2127 | 2128 | memset(t1, 0, sizeof t1); 2129 | memset(t2, 0, sizeof t2); 2130 | t1[0] = t2[0] = a[0]; 2131 | gendiv_inner(q, r, a, b, t1, t2, mod); 2132 | } 2133 | 2134 | /* 2135 | * Generic division routine. This function assumes that sizes have been 2136 | * verified to be equal to each other. Either q and r may be NULL, but 2137 | * not both. Also, q != r. 2138 | * 2139 | * If mod is non-zero, then an extra step is applied to ensure a nonnegative 2140 | * remainder. 2141 | */ 2142 | static void 2143 | gendiv(uint32_t *q, uint32_t *r, const uint32_t *a, const uint32_t *b, int mod) 2144 | { 2145 | uint32_t h; 2146 | size_t wlen; 2147 | 2148 | /* 2149 | * The inner function requires the following: 2150 | * - A non-NULL r; we need a temporary if r is NULL. 2151 | * - A nonnegative divisor, which must be a temporary since b 2152 | * might be NULL. 2153 | * - An extra temporary. 2154 | * 2155 | * We thus need either two (if r != NULL) or three (if r == NULL) 2156 | * temporaries. 2157 | */ 2158 | h = a[0] & 0x7FFFFFFF; 2159 | wlen = (h + 63) >> 5; 2160 | if (r == NULL) { 2161 | if (wlen <= (CTTK_MAX_INT_BUF / (3 * sizeof(uint32_t)))) { 2162 | gendiv_stack3(q, a, b, mod); 2163 | return; 2164 | } 2165 | #if !CTTK_NO_MALLOC 2166 | { 2167 | uint32_t *tr, *t1, *t2; 2168 | 2169 | tr = malloc(wlen * sizeof(uint32_t)); 2170 | t1 = malloc(wlen * sizeof(uint32_t)); 2171 | t2 = malloc(wlen * sizeof(uint32_t)); 2172 | if (tr != NULL && t1 != NULL && t2 != NULL) { 2173 | gendiv_inner(q, tr, a, b, t1, t2, mod); 2174 | free(tr); 2175 | free(t1); 2176 | free(t2); 2177 | return; 2178 | } 2179 | if (tr != NULL) { 2180 | free(tr); 2181 | } 2182 | if (t1 != NULL) { 2183 | free(t1); 2184 | } 2185 | if (t2 != NULL) { 2186 | free(t2); 2187 | } 2188 | } 2189 | #endif 2190 | } else { 2191 | if (wlen <= (CTTK_MAX_INT_BUF / (2 * sizeof(uint32_t)))) { 2192 | gendiv_stack2(q, r, a, b, mod); 2193 | return; 2194 | } 2195 | #if !CTTK_NO_MALLOC 2196 | { 2197 | uint32_t *t1, *t2; 2198 | 2199 | t1 = malloc(wlen * sizeof(uint32_t)); 2200 | t2 = malloc(wlen * sizeof(uint32_t)); 2201 | if (t1 != NULL && t2 != NULL) { 2202 | gendiv_inner(q, r, a, b, t1, t2, mod); 2203 | free(t1); 2204 | free(t2); 2205 | return; 2206 | } 2207 | if (t1 != NULL) { 2208 | free(t1); 2209 | } 2210 | if (t2 != NULL) { 2211 | free(t2); 2212 | } 2213 | } 2214 | #endif 2215 | } 2216 | 2217 | /* 2218 | * Could not find enough memory for temporaries... 2219 | */ 2220 | if (q != NULL) { 2221 | q[0] |= 0x80000000; 2222 | } 2223 | if (r != NULL) { 2224 | r[0] |= 0x80000000; 2225 | } 2226 | } 2227 | 2228 | /* see cttk.h */ 2229 | void 2230 | cttk_i31_divrem(uint32_t *q, uint32_t *r, const uint32_t *a, const uint32_t *b) 2231 | { 2232 | uint32_t h; 2233 | 2234 | h = a[0] & 0x7FFFFFFF; 2235 | if (h != (b[0] & 0x7FFFFFFF)) { 2236 | if (q != NULL) { 2237 | q[0] |= 0x80000000; 2238 | } 2239 | if (r != NULL) { 2240 | r[0] |= 0x80000000; 2241 | } 2242 | return; 2243 | } 2244 | if (q != NULL && h != (q[0] & 0x7FFFFFFF)) { 2245 | q[0] |= 0x80000000; 2246 | q = NULL; 2247 | } 2248 | if (r != NULL && h != (r[0] & 0x7FFFFFFF)) { 2249 | r[0] |= 0x80000000; 2250 | r = NULL; 2251 | } 2252 | if (q == NULL && r == NULL) { 2253 | return; 2254 | } 2255 | if (q == r) { 2256 | q[0] |= 0x80000000; 2257 | r[0] |= 0x80000000; 2258 | return; 2259 | } 2260 | 2261 | gendiv(q, r, a, b, 0); 2262 | } 2263 | 2264 | /* see cttk.h */ 2265 | void 2266 | cttk_i31_mod(uint32_t *d, const uint32_t *a, const uint32_t *b) 2267 | { 2268 | uint32_t h; 2269 | 2270 | h = d[0] & 0x7FFFFFFF; 2271 | if (h != (a[0] & 0x7FFFFFFF) || h != (b[0] & 0x7FFFFFFF)) { 2272 | d[0] |= 0x80000000; 2273 | return; 2274 | } 2275 | gendiv(NULL, d, a, b, 1); 2276 | } 2277 | 2278 | /* see cttk.h */ 2279 | void 2280 | cttk_i31_and(uint32_t *d, const uint32_t *a, const uint32_t *b) 2281 | { 2282 | uint32_t h; 2283 | size_t len, u; 2284 | 2285 | h = d[0] & 0x7FFFFFFF; 2286 | if (h != (a[0] & 0x7FFFFFFF) || h != (b[0] & 0x7FFFFFFF)) { 2287 | d[0] |= 0x80000000; 2288 | return; 2289 | } 2290 | len = (h + 31) >> 5; 2291 | d[0] = a[0] | b[0]; 2292 | for (u = 1; u <= len; u ++) { 2293 | d[u] = a[u] & b[u]; 2294 | } 2295 | } 2296 | 2297 | /* see cttk.h */ 2298 | void 2299 | cttk_i31_or(uint32_t *d, const uint32_t *a, const uint32_t *b) 2300 | { 2301 | uint32_t h; 2302 | size_t len, u; 2303 | 2304 | h = d[0] & 0x7FFFFFFF; 2305 | if (h != (a[0] & 0x7FFFFFFF) || h != (b[0] & 0x7FFFFFFF)) { 2306 | d[0] |= 0x80000000; 2307 | return; 2308 | } 2309 | len = (h + 31) >> 5; 2310 | d[0] = a[0] | b[0]; 2311 | for (u = 1; u <= len; u ++) { 2312 | d[u] = a[u] | b[u]; 2313 | } 2314 | } 2315 | 2316 | /* see cttk.h */ 2317 | void 2318 | cttk_i31_xor(uint32_t *d, const uint32_t *a, const uint32_t *b) 2319 | { 2320 | uint32_t h; 2321 | size_t len, u; 2322 | 2323 | h = d[0] & 0x7FFFFFFF; 2324 | if (h != (a[0] & 0x7FFFFFFF) || h != (b[0] & 0x7FFFFFFF)) { 2325 | d[0] |= 0x80000000; 2326 | return; 2327 | } 2328 | len = (h + 31) >> 5; 2329 | d[0] = a[0] | b[0]; 2330 | for (u = 1; u <= len; u ++) { 2331 | d[u] = a[u] ^ b[u]; 2332 | } 2333 | } 2334 | 2335 | /* see cttk.h */ 2336 | void 2337 | cttk_i31_eqv(uint32_t *d, const uint32_t *a, const uint32_t *b) 2338 | { 2339 | uint32_t h; 2340 | size_t len, u; 2341 | 2342 | h = d[0] & 0x7FFFFFFF; 2343 | if (h != (a[0] & 0x7FFFFFFF) || h != (b[0] & 0x7FFFFFFF)) { 2344 | d[0] |= 0x80000000; 2345 | return; 2346 | } 2347 | len = (h + 31) >> 5; 2348 | d[0] = a[0] | b[0]; 2349 | for (u = 1; u <= len; u ++) { 2350 | d[u] = a[u] ^ b[u] ^ 0x7FFFFFFF; 2351 | } 2352 | } 2353 | 2354 | /* see cttk.h */ 2355 | void 2356 | cttk_i31_not(uint32_t *d, const uint32_t *a) 2357 | { 2358 | uint32_t h; 2359 | size_t len, u; 2360 | 2361 | h = d[0] & 0x7FFFFFFF; 2362 | if (h != (a[0] & 0x7FFFFFFF)) { 2363 | d[0] |= 0x80000000; 2364 | return; 2365 | } 2366 | len = (h + 31) >> 5; 2367 | d[0] = a[0]; 2368 | for (u = 1; u <= len; u ++) { 2369 | d[u] = a[u] ^ 0x7FFFFFFF; 2370 | } 2371 | } 2372 | -------------------------------------------------------------------------------- /test/testcttk.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 Thomas Pornin 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining 5 | * a copy of this software and associated documentation files (the 6 | * "Software"), to deal in the Software without restriction, including 7 | * without limitation the rights to use, copy, modify, merge, publish, 8 | * distribute, sublicense, and/or sell copies of the Software, and to 9 | * permit persons to whom the Software is furnished to do so, subject to 10 | * the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be 13 | * included in all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 19 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 20 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | 31 | #include "cttk.h" 32 | 33 | static void 34 | check(int v, const char *fmt, ...) 35 | { 36 | if (!v) { 37 | va_list ap; 38 | 39 | va_start(ap, fmt); 40 | fprintf(stderr, "CHECK FAILED: "); 41 | vfprintf(stderr, fmt, ap); 42 | fprintf(stderr, "\n"); 43 | va_end(ap); 44 | abort(); 45 | } 46 | } 47 | 48 | /* 49 | * PRNG. Not crypto-quality, but "randomish" enough for generating test 50 | * values. 51 | */ 52 | static uint32_t rnd_state[16]; 53 | 54 | static void 55 | rnd_init(uint64_t seed) 56 | { 57 | int i; 58 | 59 | for (i = 0; i < 16; i ++) { 60 | rnd_state[i] = (uint32_t)seed; 61 | seed = (seed * 0x2F25F7F336563959) + 0xEC2BAAED5DF4DC7D; 62 | } 63 | } 64 | 65 | static void 66 | rnd_step(void) 67 | { 68 | int i; 69 | 70 | for (i = 0; i < 10; i ++) { 71 | 72 | #define QROUND(a, b, c, d) do { \ 73 | rnd_state[a] += rnd_state[b]; \ 74 | rnd_state[d] ^= rnd_state[a]; \ 75 | rnd_state[d] = (rnd_state[d] << 16) | (rnd_state[d] >> 16); \ 76 | rnd_state[c] += rnd_state[d]; \ 77 | rnd_state[b] ^= rnd_state[c]; \ 78 | rnd_state[b] = (rnd_state[b] << 12) | (rnd_state[b] >> 20); \ 79 | rnd_state[a] += rnd_state[b]; \ 80 | rnd_state[d] ^= rnd_state[a]; \ 81 | rnd_state[d] = (rnd_state[d] << 8) | (rnd_state[d] >> 24); \ 82 | rnd_state[c] += rnd_state[d]; \ 83 | rnd_state[b] ^= rnd_state[c]; \ 84 | rnd_state[b] = (rnd_state[b] << 7) | (rnd_state[b] >> 25); \ 85 | } while (0) 86 | 87 | QROUND( 0, 4, 8, 12); 88 | QROUND( 1, 5, 9, 13); 89 | QROUND( 2, 6, 10, 14); 90 | QROUND( 3, 7, 11, 15); 91 | QROUND( 0, 5, 10, 15); 92 | QROUND( 1, 6, 11, 12); 93 | QROUND( 2, 7, 8, 13); 94 | QROUND( 3, 4, 9, 14); 95 | 96 | #undef QROUND 97 | 98 | } 99 | } 100 | 101 | static uint32_t 102 | rnd32(void) 103 | { 104 | rnd_step(); 105 | return rnd_state[0]; 106 | } 107 | 108 | static uint64_t 109 | rnd64(void) 110 | { 111 | rnd_step(); 112 | return (uint64_t)rnd_state[0] + ((uint64_t)rnd_state[1] << 32); 113 | } 114 | 115 | static void 116 | rnd(void *dst, size_t len) 117 | { 118 | unsigned char *buf; 119 | size_t u; 120 | uint64_t x; 121 | 122 | buf = dst; 123 | x = 0; 124 | for (u = 0; u < len; u ++) { 125 | if ((u & 7) == 0) { 126 | x = rnd64(); 127 | } 128 | buf[u] = (unsigned char)x; 129 | x >>= 8; 130 | } 131 | } 132 | 133 | static void 134 | test_comparisons_32(void) 135 | { 136 | int i, j; 137 | 138 | printf("Test comparisons (32-bit): "); 139 | fflush(stdout); 140 | 141 | for (i = 0; i < 16 * 32; i ++) { 142 | for (j = 0; j < 16 * 32; j ++) { 143 | uint32_t xu, yu; 144 | int32_t xs, ys; 145 | int r; 146 | 147 | xu = ((uint32_t)1 << (i >> 4)) + (uint32_t)(i & 15) - 8; 148 | yu = ((uint32_t)1 << (j >> 4)) + (uint32_t)(j & 15) - 8; 149 | xs = *(int32_t *)&xu; 150 | ys = *(int32_t *)&yu; 151 | 152 | check(cttk_s32_neq0(xs).v == (uint32_t)(xs != 0), 153 | "s32_neq0: %ld", (long)xs); 154 | check(cttk_s32_neq0(ys).v == (uint32_t)(ys != 0), 155 | "s32_neq0: %ld", (long)ys); 156 | check(cttk_s32_eq0(xs).v == (uint32_t)(xs == 0), 157 | "s32_eq0: %ld", (long)xs); 158 | check(cttk_s32_eq0(ys).v == (uint32_t)(ys == 0), 159 | "s32_eq0: %ld", (long)ys); 160 | 161 | check(cttk_u32_neq0(xu).v == (uint32_t)(xu != 0), 162 | "u32_neq0: %lu", (unsigned long)xu); 163 | check(cttk_u32_neq0(yu).v == (uint32_t)(yu != 0), 164 | "u32_neq0: %lu", (unsigned long)yu); 165 | check(cttk_u32_eq0(xu).v == (uint32_t)(xu == 0), 166 | "u32_eq0: %lu", (unsigned long)xu); 167 | check(cttk_u32_eq0(yu).v == (uint32_t)(yu == 0), 168 | "u32_eq0: %lu", (unsigned long)yu); 169 | 170 | check(cttk_s32_eq(xs, ys).v == (uint32_t)(xs == ys), 171 | "s32_eq: %ld, %ld", (long)xs, (long)ys); 172 | check(cttk_s32_neq(xs, ys).v == (uint32_t)(xs != ys), 173 | "s32_neq: %ld, %ld", (long)xs, (long)ys); 174 | 175 | check(cttk_u32_eq(xu, yu).v == (uint32_t)(xu == yu), 176 | "u32_eq: %lu, %lu", 177 | (unsigned long)xu, (unsigned long)yu); 178 | check(cttk_u32_neq(xu, yu).v == (uint32_t)(xu != yu), 179 | "u32_neq: %lu, %lu", 180 | (unsigned long)xu, (unsigned long)yu); 181 | 182 | check(cttk_s32_gt(xs, ys).v == (uint32_t)(xs > ys), 183 | "s32_gt: %ld, %ld", (long)xs, (long)ys); 184 | check(cttk_s32_geq(xs, ys).v == (uint32_t)(xs >= ys), 185 | "s32_geq: %ld, %ld", (long)xs, (long)ys); 186 | check(cttk_s32_lt(xs, ys).v == (uint32_t)(xs < ys), 187 | "s32_lt: %ld, %ld", (long)xs, (long)ys); 188 | check(cttk_s32_leq(xs, ys).v == (uint32_t)(xs <= ys), 189 | "s32_leq: %ld, %ld", (long)xs, (long)ys); 190 | 191 | check(cttk_u32_gt(xu, yu).v == (uint32_t)(xu > yu), 192 | "u32_gt: %lu, %lu", 193 | (unsigned long)xu, (unsigned long)yu); 194 | check(cttk_u32_geq(xu, yu).v == (uint32_t)(xu >= yu), 195 | "u32_geq: %lu, %lu", 196 | (unsigned long)xu, (unsigned long)yu); 197 | check(cttk_u32_lt(xu, yu).v == (uint32_t)(xu < yu), 198 | "u32_lt: %lu, %lu", 199 | (unsigned long)xu, (unsigned long)yu); 200 | check(cttk_u32_leq(xu, yu).v == (uint32_t)(xu <= yu), 201 | "u32_leq: %lu, %lu", 202 | (unsigned long)xu, (unsigned long)yu); 203 | 204 | if (xs < ys) { 205 | r = -1; 206 | } else if (xs == ys) { 207 | r = 0; 208 | } else { 209 | r = 1; 210 | } 211 | check(cttk_s32_cmp(xs, ys) == r, 212 | "s32_cmp: %ld, %ld", (long)xs, (long)ys); 213 | 214 | if (xu < yu) { 215 | r = -1; 216 | } else if (xu == yu) { 217 | r = 0; 218 | } else { 219 | r = 1; 220 | } 221 | check(cttk_u32_cmp(xu, yu) == r, 222 | "u32_cmp: %ld, %ld", 223 | (unsigned long)xu, (unsigned long)yu); 224 | 225 | check(cttk_s32_gt0(xs).v == (uint32_t)(xs > 0), 226 | "s32_gt0: %ld, %ld", (long)xs); 227 | check(cttk_s32_geq0(xs).v == (uint32_t)(xs >= 0), 228 | "s32_geq0: %ld, %ld", (long)xs); 229 | check(cttk_s32_lt0(xs).v == (uint32_t)(xs < 0), 230 | "s32_lt0: %ld, %ld", (long)xs); 231 | check(cttk_s32_leq0(xs).v == (uint32_t)(xs <= 0), 232 | "s32_leq0: %ld, %ld", (long)xs); 233 | check(cttk_s32_gt0(ys).v == (uint32_t)(ys > 0), 234 | "s32_gt0: %ld, %ld", (long)ys); 235 | check(cttk_s32_geq0(ys).v == (uint32_t)(ys >= 0), 236 | "s32_geq0: %ld, %ld", (long)ys); 237 | check(cttk_s32_lt0(ys).v == (uint32_t)(ys < 0), 238 | "s32_lt0: %ld, %ld", (long)ys); 239 | check(cttk_s32_leq0(ys).v == (uint32_t)(ys <= 0), 240 | "s32_leq0: %ld, %ld", (long)ys); 241 | 242 | if (xs < 0) { 243 | r = -1; 244 | } else if (xs == 0) { 245 | r = 0; 246 | } else { 247 | r = 1; 248 | } 249 | check(cttk_s32_sign(xs) == r, 250 | "s32_sign: %ld", (long)xs); 251 | if (ys < 0) { 252 | r = -1; 253 | } else if (ys == 0) { 254 | r = 0; 255 | } else { 256 | r = 1; 257 | } 258 | check(cttk_s32_sign(ys) == r, 259 | "s32_sign: %ld", (long)ys); 260 | } 261 | 262 | if ((i & 15) == 0) { 263 | printf("."); 264 | fflush(stdout); 265 | } 266 | } 267 | 268 | printf(" done.\n"); 269 | fflush(stdout); 270 | } 271 | 272 | static void 273 | test_comparisons_64(void) 274 | { 275 | int i, j; 276 | 277 | printf("Test comparisons (64-bit): "); 278 | fflush(stdout); 279 | 280 | for (i = 0; i < 16 * 64; i ++) { 281 | for (j = 0; j < 16 * 64; j ++) { 282 | uint64_t xu, yu; 283 | int64_t xs, ys; 284 | int r; 285 | 286 | xu = ((uint64_t)1 << (i >> 4)) + (uint64_t)(i & 15) - 8; 287 | yu = ((uint64_t)1 << (j >> 4)) + (uint64_t)(j & 15) - 8; 288 | xs = *(int64_t *)&xu; 289 | ys = *(int64_t *)&yu; 290 | 291 | check(cttk_s64_neq0(xs).v == (uint32_t)(xs != 0), 292 | "s64_neq0: %lld", (long long)xs); 293 | check(cttk_s64_neq0(ys).v == (uint32_t)(ys != 0), 294 | "s64_neq0: %lld", (long long)ys); 295 | check(cttk_s64_eq0(xs).v == (uint32_t)(xs == 0), 296 | "s64_eq0: %lld", (long long)xs); 297 | check(cttk_s64_eq0(ys).v == (uint32_t)(ys == 0), 298 | "s64_eq0: %lld", (long long)ys); 299 | 300 | check(cttk_u64_neq0(xu).v == (uint32_t)(xu != 0), 301 | "u64_neq0: %llu", (unsigned long long)xu); 302 | check(cttk_u64_neq0(yu).v == (uint32_t)(yu != 0), 303 | "u64_neq0: %llu", (unsigned long long)yu); 304 | check(cttk_u64_eq0(xu).v == (uint32_t)(xu == 0), 305 | "u64_eq0: %llu", (unsigned long long)xu); 306 | check(cttk_u64_eq0(yu).v == (uint32_t)(yu == 0), 307 | "u64_eq0: %llu", (unsigned long long)yu); 308 | 309 | check(cttk_s64_eq(xs, ys).v == (uint32_t)(xs == ys), 310 | "s64_eq: %lld, %lld", 311 | (long long)xs, (long long)ys); 312 | check(cttk_s64_neq(xs, ys).v == (uint32_t)(xs != ys), 313 | "s64_neq: %lld, %lld", 314 | (long long)xs, (long long)ys); 315 | 316 | check(cttk_u64_eq(xu, yu).v == (uint32_t)(xu == yu), 317 | "u64_eq: %llu, %llu", 318 | (unsigned long long)xu, (unsigned long long)yu); 319 | check(cttk_u64_neq(xu, yu).v == (uint32_t)(xu != yu), 320 | "u64_neq: %llu, %llu", 321 | (unsigned long long)xu, (unsigned long long)yu); 322 | 323 | check(cttk_s64_gt(xs, ys).v == (uint32_t)(xs > ys), 324 | "s64_gt: %lld, %lld", 325 | (long long)xs, (long long)ys); 326 | check(cttk_s64_geq(xs, ys).v == (uint32_t)(xs >= ys), 327 | "s64_geq: %lld, %lld", 328 | (long long)xs, (long long)ys); 329 | check(cttk_s64_lt(xs, ys).v == (uint32_t)(xs < ys), 330 | "s64_lt: %lld, %lld", 331 | (long long)xs, (long long)ys); 332 | check(cttk_s64_leq(xs, ys).v == (uint32_t)(xs <= ys), 333 | "s64_leq: %lld, %lld", 334 | (long long)xs, (long long)ys); 335 | 336 | check(cttk_u64_gt(xu, yu).v == (uint32_t)(xu > yu), 337 | "u64_gt: %llu, %llu", 338 | (unsigned long long)xu, (unsigned long long)yu); 339 | check(cttk_u64_geq(xu, yu).v == (uint32_t)(xu >= yu), 340 | "u64_geq: %llu, %llu", 341 | (unsigned long long)xu, (unsigned long long)yu); 342 | check(cttk_u64_lt(xu, yu).v == (uint32_t)(xu < yu), 343 | "u64_lt: %llu, %llu", 344 | (unsigned long long)xu, (unsigned long long)yu); 345 | check(cttk_u64_leq(xu, yu).v == (uint32_t)(xu <= yu), 346 | "u64_leq: %llu, %llu", 347 | (unsigned long long)xu, (unsigned long long)yu); 348 | 349 | if (xs < ys) { 350 | r = -1; 351 | } else if (xs == ys) { 352 | r = 0; 353 | } else { 354 | r = 1; 355 | } 356 | check(cttk_s64_cmp(xs, ys) == r, 357 | "s64_cmp: %lld, %lld", 358 | (long long)xs, (long long)ys); 359 | 360 | if (xu < yu) { 361 | r = -1; 362 | } else if (xu == yu) { 363 | r = 0; 364 | } else { 365 | r = 1; 366 | } 367 | check(cttk_u64_cmp(xu, yu) == r, 368 | "u64_cmp: %lld, %lld", 369 | (unsigned long long)xu, (unsigned long long)yu); 370 | 371 | check(cttk_s64_gt0(xs).v == (uint32_t)(xs > 0), 372 | "s64_gt0: %lld, %lld", (long long)xs); 373 | check(cttk_s64_geq0(xs).v == (uint32_t)(xs >= 0), 374 | "s64_geq0: %lld, %lld", (long long)xs); 375 | check(cttk_s64_lt0(xs).v == (uint32_t)(xs < 0), 376 | "s64_lt0: %lld, %lld", (long long)xs); 377 | check(cttk_s64_leq0(xs).v == (uint32_t)(xs <= 0), 378 | "s64_leq0: %lld, %lld", (long long)xs); 379 | check(cttk_s64_gt0(ys).v == (uint32_t)(ys > 0), 380 | "s64_gt0: %lld, %lld", (long long)ys); 381 | check(cttk_s64_geq0(ys).v == (uint32_t)(ys >= 0), 382 | "s64_geq0: %lld, %lld", (long long)ys); 383 | check(cttk_s64_lt0(ys).v == (uint32_t)(ys < 0), 384 | "s64_lt0: %lld, %lld", (long long)ys); 385 | check(cttk_s64_leq0(ys).v == (uint32_t)(ys <= 0), 386 | "s64_leq0: %lld, %lld", (long long)ys); 387 | 388 | if (xs < 0) { 389 | r = -1; 390 | } else if (xs == 0) { 391 | r = 0; 392 | } else { 393 | r = 1; 394 | } 395 | check(cttk_s64_sign(xs) == r, 396 | "s64_sign: %lld", (long long)xs); 397 | if (ys < 0) { 398 | r = -1; 399 | } else if (ys == 0) { 400 | r = 0; 401 | } else { 402 | r = 1; 403 | } 404 | check(cttk_s64_sign(ys) == r, 405 | "s64_sign: %lld", (long long)ys); 406 | } 407 | 408 | if ((i & 15) == 0) { 409 | printf("."); 410 | fflush(stdout); 411 | } 412 | } 413 | 414 | printf(" done.\n"); 415 | fflush(stdout); 416 | } 417 | 418 | static void 419 | test_comparisons_buffers(void) 420 | { 421 | unsigned char buf1[200], buf2[sizeof buf1]; 422 | size_t u; 423 | 424 | printf("Test comparisons (buffers): "); 425 | fflush(stdout); 426 | 427 | rnd_init(2); 428 | 429 | for (u = 0; u < sizeof buf1; u ++) { 430 | size_t v; 431 | int i; 432 | 433 | for (i = 0; i < 20; i ++) { 434 | rnd(buf1, u); 435 | memcpy(buf2, buf1, u); 436 | check(cttk_array_eq(buf1, buf2, u).v, 437 | "array_eq 1 (%zu,%d)", u, i); 438 | check(!cttk_array_neq(buf1, buf2, u).v, 439 | "array_neq 1 (%zu,%d)", u, i); 440 | check(cttk_array_cmp(buf1, buf2, u) == 0, 441 | "array_cmp 1 (%zu,%d)", u, i); 442 | } 443 | for (v = 0; v < u; v ++) { 444 | int cc; 445 | 446 | buf2[v] ^= 0xA5; 447 | check(!cttk_array_eq(buf1, buf2, u).v, 448 | "array_eq 2 (%zu,%zu)", u, v); 449 | check(cttk_array_neq(buf1, buf2, u).v, 450 | "array_neq 2 (%zu,%zu)", u, v); 451 | cc = buf1[v] < buf2[v] ? -1 : 1; 452 | check(cttk_array_cmp(buf1, buf2, u) == cc, 453 | "array_cmp 2 (%zu,%zu)", u, v); 454 | buf2[v] = buf1[v]; 455 | } 456 | 457 | if (u % 8 == 0) { 458 | printf("."); 459 | fflush(stdout); 460 | } 461 | } 462 | 463 | printf(" done.\n"); 464 | fflush(stdout); 465 | } 466 | 467 | static void 468 | test_hex(void) 469 | { 470 | static const unsigned char databin[] = { 471 | 0x38, 0xF2, 0x45, 0x86, 0x85, 0x82, 0xE3, 0x59, 472 | 0x83, 0x3D, 0xE0, 0x0D, 0x90, 0x50, 0x5F, 0xA8, 473 | 0x41, 0xBF, 0x0A, 0xE3, 0x01, 0x5B, 0x70, 0xCA, 474 | 0x16, 0x0B, 0xDB, 0x63, 0x57, 0xF1, 0xB9, 0xE3, 475 | 0x9A, 0x3F, 0xF6, 0x49, 0x28, 0xCA, 0xC9, 0x4F, 476 | 0xCB, 0x6E, 0x44, 0x11, 0x92, 0x82, 0xC4, 0x72, 477 | 0xF4, 0x31, 0xB1, 0xDF, 0x0C, 0xDE, 0xA5, 0x85, 478 | 0x03, 0x26, 0x4C, 0x87, 0xC4, 0x76, 0x5E, 0x5C, 479 | 0x6C, 0x61, 0x63, 0x7F, 0x93, 0xC1, 0xE1, 0x60, 480 | 0xC3, 0x3C, 0x2C, 0x11, 0x4C, 0x83, 0x6C, 0x1A, 481 | 0x57, 0x2C, 0x72, 0x1B, 0x63, 0x44, 0x0B, 0xB8, 482 | 0x4A, 0x46, 0x7C, 0x42, 0xAA, 0xBA, 0x56, 0xF2, 483 | 0x67, 0x5E, 0xA4, 0xA0, 0x0D, 0x7A, 0xF9, 0x59, 484 | 0xE1, 0xF5, 0xCA, 0xE7, 0x0B, 0xA0, 0xA6, 0xD7, 485 | 0x3E, 0xFE, 0xCF, 0x08, 0xDF, 0xE4, 0xA4, 0xBF, 486 | 0x7D, 0x4B, 0x84, 0x91, 0x17, 0xF2, 0x0C, 0x3B, 487 | 0x66, 0x58, 0xF3, 0x27, 0x4C, 0x88, 0x5C, 0x09, 488 | 0x47, 0xD0, 0xE3, 0x00, 0x40, 0x16, 0xBC, 0xFC, 489 | 0x56, 0x2C, 0x58, 0x3E, 0x95, 0xA2, 0x1C, 0x45, 490 | 0x7D, 0x18, 0xA9, 0xBC, 0xD1, 0x45, 0x54, 0x43, 491 | 0x5B, 0x46, 0x55, 0xBB, 0xA2, 0x23, 0xB1, 0x43, 492 | 0x1D, 0x02, 0x8A, 0xD2, 0x14, 0x7A, 0x3C, 0x36, 493 | 0x61, 0x21, 0x39, 0xA6, 0x7B, 0xC1, 0xB0, 0x13, 494 | 0x00, 0xCC, 0xAB, 0x50, 0x9F, 0x1D, 0x40, 0x01, 495 | 0xD2, 0x84, 0x55, 0x6C, 0xF5, 0x0E, 0x14, 0x74, 496 | 0xBC, 0xF1, 0x1D, 0x17, 0xE4, 0x98, 0x70, 0x2C, 497 | 0x1A, 0xD7, 0x66, 0x67, 0x33, 0xEE, 0x20, 0xE9, 498 | 0x5D, 0x93, 0xD0, 0xF4, 0x0A, 0xD8, 0x6D, 0x23, 499 | 0xF1, 0x08, 0x9D, 0x70, 0x1B, 0x97, 0xAC, 0x99, 500 | 0xB0, 0xE5, 0x3A, 0x4E, 0x7E, 0x46, 0xB2, 0x81, 501 | 0x24, 0xB9, 0x08, 0x23, 0xD2, 0x21, 0xF9, 0x3D, 502 | 0xB6, 0x96, 0xF4, 0xF6, 0x06, 0x65, 0x66, 0x04 503 | }; 504 | 505 | char datastr[1 + ((sizeof databin) << 1)]; 506 | char tmp[sizeof datastr]; 507 | unsigned char buf[(sizeof databin) + 1]; 508 | size_t u, v, w; 509 | int i, j; 510 | const char *err; 511 | 512 | printf("Test hex: "); 513 | fflush(stdout); 514 | 515 | for (i = 0; i < 2; i ++) { 516 | unsigned flags; 517 | 518 | flags = (i == 0) ? 0 : CTTK_HEX_UPPERCASE; 519 | for (u = 0; u < sizeof databin; u ++) { 520 | sprintf(datastr + (u << 1), 521 | (i == 0) ? "%02x" : "%02X", databin[u]); 522 | } 523 | for (u = 0; u <= sizeof datastr; u ++) { 524 | memset(tmp, 'T', sizeof tmp); 525 | v = cttk_bintohex_gen(tmp, u, 526 | databin, sizeof databin, flags); 527 | if (u == 0) { 528 | check(v == 0, "bintohex 1"); 529 | check(tmp[0] == 'T', "bintohex 2"); 530 | } else { 531 | check(v == u - 1, "bintohex 3"); 532 | check(tmp[v] == 0, "bintohex 4"); 533 | check(memcmp(datastr, tmp, v) == 0, 534 | "bintohex 5"); 535 | } 536 | } 537 | for (u = 0; u <= sizeof databin; u ++) { 538 | memset(tmp, 'U', sizeof tmp); 539 | v = cttk_bintohex_gen(tmp, sizeof tmp, 540 | databin, u, flags); 541 | check(v == (u << 1), "bintohex 6"); 542 | check(tmp[v] == 0, "bintohex 7"); 543 | check(memcmp(datastr, tmp, v) == 0, "bintohex 8"); 544 | v = cttk_bintohex_gen(NULL, 0, databin, u, flags); 545 | check(v == (u << 1), "bintohex 9"); 546 | } 547 | printf("."); 548 | fflush(stdout); 549 | } 550 | 551 | for (i = 0; i < 2; i ++) { 552 | for (u = 0; u < sizeof databin; u ++) { 553 | sprintf(datastr + (u << 1), 554 | (i == 0) ? "%02x" : "%02X", databin[u]); 555 | } 556 | for (u = 0; u <= sizeof datastr; u ++) { 557 | memset(buf, 0xFF, sizeof buf); 558 | v = cttk_hextobin_gen(buf, sizeof buf, 559 | datastr, u, &err, 0); 560 | check(v == (u >> 1), "hextobin 1"); 561 | if (u == sizeof datastr) { 562 | check(err == datastr + u - 1, "hextobin 2"); 563 | } else if ((u & 1) == 1) { 564 | check(err == datastr + u, "hextobin 3"); 565 | } else { 566 | check(err == NULL, "hextobin 4"); 567 | } 568 | check(memcmp(buf, databin, v) == 0, "hextobin 5"); 569 | check(buf[v] == 0xFF, "hextobin 6"); 570 | 571 | v = cttk_hextobin_gen(NULL, 0, datastr, u, &err, 0); 572 | check(v == (u >> 1), "hextobin 7"); 573 | v = cttk_hextobin_gen(NULL, 0, datastr, u, NULL, 0); 574 | check(v == (u >> 1), "hextobin 8"); 575 | 576 | memset(buf, 0xFF, sizeof buf); 577 | v = cttk_hextobin_gen(buf, sizeof buf, 578 | datastr, u, &err, CTTK_HEX_PAD_ODD); 579 | if (u == sizeof datastr) { 580 | check(v == (u >> 1), "hextobin 9"); 581 | check(err == datastr + u - 1, "hextobin 10"); 582 | } else if ((u & 1) == 1) { 583 | check(v == ((u + 1) >> 1), "hextobin 11"); 584 | check(err == NULL, "hextobin 12"); 585 | v --; 586 | check(buf[v] == (databin[v] & 0xF0), 587 | "hextobin 13"); 588 | } else { 589 | check(v == (u >> 1), "hextobin 14"); 590 | check(err == NULL, "hextobin 15"); 591 | } 592 | check(memcmp(buf, databin, v) == 0, "hextobin 16"); 593 | } 594 | 595 | for (u = 0; u <= sizeof databin; u ++) { 596 | memset(buf, 0xFF, sizeof buf); 597 | v = cttk_hextobin_gen(buf, u, 598 | datastr, (sizeof databin) << 1, &err, 0); 599 | check(u == v, "hextobin 17"); 600 | check(buf[v] == 0xFF, "hextobin 18"); 601 | if (u == sizeof databin) { 602 | check(err == NULL, "hextobin 19"); 603 | } else { 604 | check(err == datastr + (u << 1), "hextobin 20"); 605 | } 606 | check(memcmp(buf, databin, u) == 0, "hextobin 21"); 607 | } 608 | 609 | for (u = 0, v = 0; datastr[u] && v < (sizeof tmp) - 10; u ++) { 610 | for (j = 0; j < (int)(u % 7); j ++) { 611 | tmp[v] = 1 + (v & 31); 612 | v ++; 613 | } 614 | tmp[v ++] = datastr[u]; 615 | } 616 | if ((u & 1) != 0) { 617 | v --; 618 | } 619 | memset(buf, 0xFF, sizeof buf); 620 | w = cttk_hextobin_gen(buf, sizeof buf, 621 | tmp, v, &err, CTTK_HEX_SKIP_WS); 622 | check(w == (u >> 1), "hextobin 22"); 623 | check(buf[w] == 0xFF, "hextobin 23"); 624 | check(err == NULL, "hextobin 24"); 625 | check(memcmp(buf, databin, w) == 0, "hextobin 25"); 626 | 627 | printf("."); 628 | fflush(stdout); 629 | } 630 | 631 | printf(" done.\n"); 632 | fflush(stdout); 633 | } 634 | 635 | static char 636 | b64char(int x) 637 | { 638 | return "ABCDEFGHIJKLMNOPQRSTUVWXYZ" 639 | "abcdefghijklmnopqrstuvwxyz0123456789+/" [x]; 640 | } 641 | 642 | static void 643 | b64enc(char *dst, const unsigned char *buf, size_t len, 644 | int pad, int line_len, int crlf) 645 | { 646 | size_t u, v; 647 | int lc; 648 | 649 | lc = 0; 650 | v = 0; 651 | for (u = 0; (u + 2) < len; u += 3) { 652 | uint32_t x; 653 | 654 | x = ((uint32_t)buf[u] << 16) 655 | | ((uint32_t)buf[u + 1] << 8) 656 | | (uint32_t)buf[u + 2]; 657 | dst[v ++] = b64char(x >> 18); 658 | dst[v ++] = b64char((x >> 12) & 63); 659 | dst[v ++] = b64char((x >> 6) & 63); 660 | dst[v ++] = b64char(x & 63); 661 | lc ++; 662 | if (lc == line_len) { 663 | lc = 0; 664 | if (crlf) { 665 | dst[v ++] = '\r'; 666 | } 667 | dst[v ++] = '\n'; 668 | } 669 | } 670 | if (u == len - 1) { 671 | uint32_t x; 672 | 673 | x = buf[u]; 674 | dst[v ++] = b64char(x >> 2); 675 | dst[v ++] = b64char((x << 4) & 63); 676 | if (pad) { 677 | dst[v ++] = '='; 678 | dst[v ++] = '='; 679 | } 680 | lc ++; 681 | } else if (u == len - 2) { 682 | uint32_t x; 683 | 684 | x = ((uint32_t)buf[u] << 8) | (uint32_t)buf[u + 1]; 685 | dst[v ++] = b64char(x >> 10); 686 | dst[v ++] = b64char((x >> 4) & 63); 687 | dst[v ++] = b64char((x << 2) & 63); 688 | if (pad) { 689 | dst[v ++] = '='; 690 | } 691 | lc ++; 692 | } 693 | if (lc != 0 && line_len != 0) { 694 | if (crlf) { 695 | dst[v ++] = '\r'; 696 | } 697 | dst[v ++] = '\n'; 698 | } 699 | dst[v ++] = 0; 700 | } 701 | 702 | static void 703 | test_base64(void) 704 | { 705 | /* 706 | * Test data is a random 256-byte blob. 707 | */ 708 | static const unsigned char databin[] = { 709 | 0x6D, 0xDD, 0x85, 0x66, 0xB3, 0x64, 0xB6, 0x41, 710 | 0xF6, 0x70, 0x69, 0xD7, 0x20, 0xCB, 0x2A, 0x10, 711 | 0xE1, 0x33, 0x34, 0xE1, 0x8B, 0x26, 0xB9, 0x71, 712 | 0xFD, 0xE1, 0x58, 0x87, 0xFD, 0xB2, 0xD1, 0xDA, 713 | 0x9D, 0x93, 0x04, 0x67, 0x8A, 0xDC, 0x17, 0xDA, 714 | 0xCB, 0x38, 0xE5, 0xB1, 0x81, 0xCF, 0x8A, 0xF9, 715 | 0xDB, 0x51, 0xC5, 0x70, 0x2F, 0x26, 0x88, 0x7F, 716 | 0x36, 0x65, 0xD4, 0xCD, 0x22, 0x67, 0xF9, 0x1D, 717 | 0x72, 0x9F, 0xE1, 0xFE, 0x2B, 0xF8, 0xF6, 0x7D, 718 | 0x3B, 0x2B, 0xEE, 0x84, 0x3F, 0xAF, 0xEF, 0x01, 719 | 0x26, 0x0B, 0x21, 0x21, 0x52, 0x49, 0xE2, 0xFC, 720 | 0x76, 0x46, 0x3B, 0x70, 0xA2, 0x94, 0x92, 0x1C, 721 | 0xAF, 0x7D, 0x50, 0xE0, 0x2C, 0x6D, 0x83, 0xA9, 722 | 0x09, 0x56, 0x21, 0x5D, 0x8D, 0x56, 0x26, 0x06, 723 | 0x15, 0x63, 0x7E, 0xB3, 0x8C, 0x45, 0x6C, 0x7D, 724 | 0x82, 0xBD, 0xA0, 0xC7, 0x8E, 0x58, 0xDD, 0xDA, 725 | 0x70, 0xB8, 0x11, 0x83, 0x2E, 0x81, 0xBC, 0xCF, 726 | 0xAD, 0x5D, 0x09, 0xDA, 0x60, 0x03, 0xE8, 0x9E, 727 | 0x72, 0xF9, 0xAE, 0xDC, 0xAC, 0x56, 0x6F, 0xF8, 728 | 0xEB, 0x44, 0x58, 0xBA, 0x95, 0xB9, 0x2B, 0x71, 729 | 0x85, 0xD4, 0x58, 0x74, 0xA2, 0x54, 0xC4, 0x66, 730 | 0x80, 0xE4, 0x67, 0xFE, 0x09, 0x70, 0xD5, 0x2A, 731 | 0x05, 0x12, 0x63, 0x77, 0xFB, 0xD8, 0x19, 0x4B, 732 | 0xA6, 0xBE, 0xFE, 0x01, 0x09, 0x7D, 0x52, 0x6A, 733 | 0x76, 0x8B, 0x12, 0x76, 0x70, 0x67, 0xBA, 0xEC, 734 | 0x26, 0x97, 0x6C, 0x60, 0xBD, 0x67, 0x8E, 0xD1, 735 | 0xCA, 0x58, 0xD4, 0x87, 0x54, 0x8E, 0x7D, 0xAA, 736 | 0x4A, 0x0F, 0xE2, 0x92, 0x13, 0xDF, 0x5E, 0x9F, 737 | 0x11, 0xB7, 0x44, 0x70, 0x84, 0x04, 0x8F, 0x03, 738 | 0xB4, 0xBB, 0x83, 0x87, 0x76, 0x1C, 0xC5, 0xB7, 739 | 0xF2, 0xF8, 0x2C, 0xD4, 0xFF, 0xAC, 0xDA, 0xAD, 740 | 0xAA, 0x59, 0xBA, 0xD9, 0xA9, 0x8D, 0x54, 0x37 741 | }; 742 | 743 | static const char datab64[] = 744 | "bd2FZrNktkH2cGnXIMsqEOEzNOGLJrlx/eFYh/2y0dqdkwRnitwX2ss45bGBz4r521HFcC8miH82" 745 | "ZdTNImf5HXKf4f4r+PZ9OyvuhD+v7wEmCyEhUkni/HZGO3CilJIcr31Q4Cxtg6kJViFdjVYmBhVj" 746 | "frOMRWx9gr2gx45Y3dpwuBGDLoG8z61dCdpgA+iecvmu3KxWb/jrRFi6lbkrcYXUWHSiVMRmgORn" 747 | "/glw1SoFEmN3+9gZS6a+/gEJfVJqdosSdnBnuuwml2xgvWeO0cpY1IdUjn2qSg/ikhPfXp8Rt0Rw" 748 | "hASPA7S7g4d2HMW38vgs1P+s2q2qWbrZqY1UNw=="; 749 | 750 | size_t u; 751 | 752 | printf("Test base64: "); 753 | fflush(stdout); 754 | 755 | for (u = 0; u <= sizeof databin; u ++) { 756 | char text[(sizeof databin) << 1], tref[sizeof text]; 757 | unsigned char data[sizeof databin]; 758 | int ff; 759 | size_t len; 760 | 761 | /* 762 | * Check test Base64 encoder against reference. 763 | */ 764 | b64enc(tref, databin, u, 1, 0, 0); 765 | if (u == sizeof databin) { 766 | check(strcmp(tref, datab64) == 0, "b64enc ref"); 767 | } else { 768 | len = 4 * (u / 3); 769 | check(memcmp(tref, datab64, len) == 0, "b64enc ref"); 770 | } 771 | 772 | /* 773 | * Test encoder with all flag combinations and truncation. 774 | */ 775 | for (ff = 0; ff < 10; ff ++) { 776 | int pad, line_len, crlf; 777 | unsigned flags; 778 | size_t v; 779 | 780 | flags = 0; 781 | pad = ff / 5; 782 | if (!pad) { 783 | flags |= CTTK_B64ENC_NO_PAD; 784 | } 785 | switch (ff % 3) { 786 | case 0: 787 | line_len = 0; 788 | crlf = 0; 789 | break; 790 | case 1: 791 | line_len = 19; 792 | crlf = 0; 793 | flags |= CTTK_B64ENC_NEWLINE; 794 | break; 795 | case 2: 796 | line_len = 16; 797 | crlf = 0; 798 | flags |= CTTK_B64ENC_NEWLINE; 799 | flags |= CTTK_B64ENC_LINE64; 800 | break; 801 | case 3: 802 | line_len = 19; 803 | crlf = 1; 804 | flags |= CTTK_B64ENC_NEWLINE; 805 | flags |= CTTK_B64ENC_CRLF; 806 | break; 807 | case 4: 808 | line_len = 16; 809 | crlf = 1; 810 | flags |= CTTK_B64ENC_NEWLINE; 811 | flags |= CTTK_B64ENC_LINE64; 812 | flags |= CTTK_B64ENC_CRLF; 813 | break; 814 | } 815 | 816 | b64enc(tref, databin, u, pad, line_len, crlf); 817 | len = cttk_bintob64_gen(NULL, 0, databin, u, flags); 818 | check(len == strlen(tref), "b64enc (%zu, %d) 1", u, ff); 819 | len = cttk_bintob64_gen(text, sizeof text, 820 | databin, u, flags); 821 | check(len == strlen(tref), "b64enc (%zu, %d) 2", u, ff); 822 | check(len == strlen(text), "b64enc (%zu, %d) 3", u, ff); 823 | check(!strcmp(text, tref), "b64enc (%zu, %d) 4", u, ff); 824 | check(cttk_bintob64_gen(text, 0, databin, 825 | u, flags) == 0, "b64enc (%zu, %d) 5", u, ff); 826 | 827 | for (v = 0; v <= len; v ++) { 828 | size_t len2; 829 | 830 | len2 = cttk_bintob64_gen(text, v + 1, 831 | databin, u, flags); 832 | check(len2 == v, 833 | "b64enc (%zu, %d, %zu) 6", u, ff, v); 834 | check(len2 == strlen(text), 835 | "b64enc (%zu, %d, %zu) 7", u, ff, v); 836 | check(memcmp(text, tref, len2) == 0, 837 | "b64enc (%zu, %d, %zu) 8", u, ff, v); 838 | } 839 | } 840 | 841 | /* 842 | * Test decoder with added whitespace and non-whitespace. 843 | */ 844 | for (ff = 0; ff < 2; ff ++) { 845 | size_t v; 846 | 847 | b64enc(tref + 1, databin, u, ff, 0, 0); 848 | len = strlen(tref + 1); 849 | for (v = 0; v <= len; v ++) { 850 | size_t len2, len3; 851 | const char *err; 852 | 853 | if (v == 0) { 854 | tref[0] = ' '; 855 | } else { 856 | tref[v - 1] = tref[v]; 857 | tref[v] = ' '; 858 | } 859 | err = datab64; 860 | len2 = cttk_b64tobin_gen(data, sizeof data, 861 | tref, len + 1, &err, 862 | ff ? 0 : CTTK_B64DEC_NO_PAD); 863 | check(len2 == u, 864 | "b64dec (%zu, %d, %zu) 1", u, ff, v); 865 | check(err == NULL, 866 | "b64dec (%zu, %d, %zu) 2", u, ff, v); 867 | check(memcmp(data, databin, u) == 0, 868 | "b64dec (%zu, %d, %zu) 3", u, ff, v); 869 | 870 | err = datab64; 871 | len2 = cttk_b64tobin_gen(data, sizeof data, 872 | tref, len + 1, &err, 873 | (ff ? 0 : CTTK_B64DEC_NO_PAD) 874 | | CTTK_B64DEC_NO_WS); 875 | check(err == tref + v, 876 | "b64dec (%zu, %d, %zu) 4", u, ff, v); 877 | len3 = (v * 3) / 4; 878 | if (len3 > u) { 879 | len3 = u; 880 | } 881 | check(len2 == len3, 882 | "b64dec (%zu, %d, %zu) 5", u, ff, v); 883 | check(memcmp(data, databin, len2) == 0, 884 | "b64dec (%zu, %d, %zu) 6", u, ff, v); 885 | 886 | tref[v] = '%'; 887 | err = datab64; 888 | len2 = cttk_b64tobin_gen(data, sizeof data, 889 | tref, len + 1, &err, 890 | ff ? 0 : CTTK_B64DEC_NO_PAD); 891 | check(err == tref + v, 892 | "b64dec (%zu, %d, %zu) 7", u, ff, v); 893 | len3 = (v * 3) / 4; 894 | if (len3 > u) { 895 | len3 = u; 896 | } 897 | check(len2 == len3, 898 | "b64dec (%zu, %d, %zu) 8", u, ff, v); 899 | check(memcmp(data, databin, len2) == 0, 900 | "b64dec (%zu, %d, %zu) 9", u, ff, v); 901 | } 902 | } 903 | 904 | /* 905 | * Test decoder with a truncated input. 906 | */ 907 | for (ff = 0; ff < 2; ff ++) { 908 | size_t v; 909 | 910 | b64enc(tref, databin, u, ff, 0, 0); 911 | len = strlen(tref); 912 | for (v = 0; v <= len; v ++) { 913 | size_t len2, len3; 914 | const char *err, *err2; 915 | 916 | err = datab64; 917 | len2 = cttk_b64tobin_gen(data, sizeof data, 918 | tref, v, &err, 919 | ff ? 0 : CTTK_B64DEC_NO_PAD); 920 | len3 = (v * 3) / 4; 921 | if (len3 > u) { 922 | len3 = u; 923 | } 924 | check(len2 == len3, 925 | "b64trunc1 (%zu, %d, %zu) 1", u, ff, v); 926 | if (ff) { 927 | if (v % 4 == 0) { 928 | err2 = NULL; 929 | } else { 930 | err2 = tref + v; 931 | } 932 | } else { 933 | int ok; 934 | 935 | if (len3 == u) { 936 | ok = 1; 937 | } else if (v % 4 == 0) { 938 | ok = 1; 939 | } else if (v % 4 == 1) { 940 | ok = 0; 941 | } else if (v % 4 == 2) { 942 | ok = !(databin[len3] & 0xF0); 943 | } else { 944 | ok = !(databin[len3] & 0xC0); 945 | } 946 | err2 = ok ? NULL : tref + v; 947 | } 948 | check(err == err2, 949 | "b64trunc1 (%zu, %d, %zu) 2", u, ff, v); 950 | check(memcmp(data, databin, u) == 0, 951 | "b64trunc1 (%zu, %d, %zu) 3", u, ff, v); 952 | } 953 | } 954 | 955 | /* 956 | * Test decoder with a truncated output. 957 | */ 958 | for (ff = 0; ff < 2; ff ++) { 959 | size_t v; 960 | 961 | b64enc(tref, databin, u, ff, 0, 0); 962 | len = strlen(tref); 963 | for (v = 0; v <= u; v ++) { 964 | size_t len2; 965 | const char *err, *err2; 966 | 967 | err = datab64; 968 | len2 = cttk_b64tobin_gen(data, v, 969 | tref, len, &err, 970 | ff ? 0 : CTTK_B64DEC_NO_PAD); 971 | check(len2 == v, 972 | "b64trunc2 (%zu, %d, %zu) 1", u, ff, v); 973 | err2 = (v == u) ? NULL : tref + (4 * v + 2) / 3; 974 | check(err == err2, 975 | "b64trunc2 (%zu, %d, %zu) 2", u, ff, v); 976 | check(memcmp(data, databin, v) == 0, 977 | "b64trunc2 (%zu, %d, %zu) 3", u, ff, v); 978 | } 979 | } 980 | 981 | if ((u & 7) == 0) { 982 | printf("."); 983 | fflush(stdout); 984 | } 985 | } 986 | 987 | printf(" done.\n"); 988 | fflush(stdout); 989 | } 990 | 991 | static void 992 | test_mul(void) 993 | { 994 | int i, j, k; 995 | uint32_t xu32, yu32; 996 | int32_t xs32, ys32; 997 | uint64_t xu64, yu64; 998 | int64_t xs64, ys64; 999 | 1000 | printf("Test mul: "); 1001 | fflush(stdout); 1002 | 1003 | for (i = 0; i < 32 * 64; i ++) { 1004 | k = i >> 5; 1005 | xu64 = (uint64_t)((i & 15) - 8); 1006 | if (i < 32 * 4) { 1007 | xu64 >>= k; 1008 | } else { 1009 | xu64 <<= k; 1010 | xu64 ^= (uint64_t)((i >> 4) & 1) << (i >> 6); 1011 | } 1012 | xs64 = *(int64_t *)&xu64; 1013 | xu32 = (uint32_t)xu64; 1014 | xs32 = *(int32_t *)&xu32; 1015 | for (j = 0; j < 32 * 64; j ++) { 1016 | uint32_t ru32; 1017 | int32_t rs32; 1018 | uint64_t ru32w, ru64; 1019 | int64_t rs32w, rs64; 1020 | 1021 | k = j >> 5; 1022 | yu64 = (uint64_t)((j & 15) - 8); 1023 | if (j < 32 * 4) { 1024 | yu64 >>= k; 1025 | } else { 1026 | yu64 <<= k; 1027 | yu64 ^= (uint64_t)((j >> 4) & 1) << (j >> 6); 1028 | } 1029 | ys64 = *(int64_t *)&yu64; 1030 | yu32 = (uint32_t)yu64; 1031 | ys32 = *(int32_t *)&yu32; 1032 | 1033 | ru32 = xu32 * yu32; 1034 | rs32 = *(int32_t *)&ru32; 1035 | ru32w = (uint64_t)xu32 * (uint64_t)yu32; 1036 | rs32w = (int64_t)xs32 * (int64_t)ys32; 1037 | ru64 = xu64 * yu64; 1038 | rs64 = xs64 * ys64; 1039 | 1040 | check(cttk_mulu32(xu32, yu32) == ru32, 1041 | "mulu32: %lu, %lu\n", 1042 | (unsigned long)xu32, 1043 | (unsigned long)yu32); 1044 | check(cttk_muls32(xs32, ys32) == rs32, 1045 | "muls32: %llu, %llu\n", 1046 | (long)xs32, 1047 | (long)ys32); 1048 | check(cttk_mulu32w(xu32, yu32) == ru32w, 1049 | "mulu32w: %lu, %lu\n", 1050 | (unsigned long)xu32, 1051 | (unsigned long)yu32); 1052 | check(cttk_muls32w(xs32, ys32) == rs32w, 1053 | "muls32w: %lu, %lu\n", 1054 | (long)xs32, 1055 | (long)ys32); 1056 | check(cttk_mulu64(xu64, yu64) == ru64, 1057 | "mulu64: %llu, %llu\n", 1058 | (unsigned long long)xu64, 1059 | (unsigned long long)yu64); 1060 | check(cttk_muls64(xs64, ys64) == rs64, 1061 | "muls64: %llu, %llu\n", 1062 | (long long)xs64, 1063 | (long long)ys64); 1064 | } 1065 | 1066 | if ((i & 31) == 0) { 1067 | printf("."); 1068 | fflush(stdout); 1069 | } 1070 | } 1071 | 1072 | printf(" done.\n"); 1073 | fflush(stdout); 1074 | } 1075 | 1076 | static void 1077 | test_bitlength(void) 1078 | { 1079 | int i, j; 1080 | 1081 | printf("Test bitlength: "); 1082 | fflush(stdout); 1083 | 1084 | check(cttk_u32_bitlength(0) == 0, "bitlength 0"); 1085 | 1086 | for (i = 0; i <= 31; i ++) { 1087 | for (j = 0; j < 256; j ++) { 1088 | uint32_t x, y, bl; 1089 | 1090 | x = (uint32_t)1 << i; 1091 | if (j < 64) { 1092 | y = (uint32_t)j; 1093 | if (y < x) { 1094 | x += y; 1095 | } 1096 | } else if (j < 128) { 1097 | if (i >= 6) { 1098 | y = (uint32_t)(j - 64); 1099 | x += y << (i - 6); 1100 | } 1101 | } else if (j < 192) { 1102 | y = (uint32_t)(j - 128); 1103 | if (y < x) { 1104 | x = (x << 1) - 1; 1105 | x -= y; 1106 | } 1107 | } else { 1108 | if (i >= 6) { 1109 | x = (x << 1) - 1; 1110 | y = (uint32_t)(j - 192); 1111 | x -= y << (i - 6); 1112 | } 1113 | } 1114 | 1115 | bl = cttk_u32_bitlength(x); 1116 | check(bl == (uint32_t)(i + 1), 1117 | "bitlength: %08lX -> %u (%d,%d)", 1118 | (unsigned long)x, (unsigned)bl, i, j); 1119 | } 1120 | } 1121 | 1122 | printf("done.\n"); 1123 | fflush(stdout); 1124 | } 1125 | 1126 | /* 1127 | * Custom rudimentary bigint implementation for test purposes. 1128 | * Each integer is an array of 16-bit words, in little-endian order. 1129 | * Maximum size is 512 bits. 1130 | */ 1131 | typedef struct { 1132 | uint16_t v[32]; 1133 | } zint; 1134 | 1135 | static void 1136 | zint_zero(zint *z) 1137 | { 1138 | memset(z->v, 0, sizeof z->v); 1139 | } 1140 | 1141 | static void 1142 | zint_set_u64(zint *z, uint64_t x) 1143 | { 1144 | memset(z->v, 0, sizeof z->v); 1145 | z->v[0] = (uint16_t)x; 1146 | z->v[1] = (uint16_t)(x >> 16); 1147 | z->v[2] = (uint16_t)(x >> 32); 1148 | z->v[3] = (uint16_t)(x >> 48); 1149 | } 1150 | 1151 | /* unused 1152 | static void 1153 | zint_set_s64(zint *z, int64_t x) 1154 | { 1155 | zint_set_u64(z, (uint64_t)x); 1156 | if (x < 0) { 1157 | memset(z->v + 4, 0xFF, (sizeof z->v) - 4 * sizeof(uint16_t)); 1158 | } 1159 | } 1160 | */ 1161 | 1162 | static unsigned 1163 | zint_bitlength(const zint *z) 1164 | { 1165 | unsigned w; 1166 | int i; 1167 | 1168 | if (z->v[31] >= 0x8000) { 1169 | w = 0xFFFF; 1170 | } else { 1171 | w = 0x0000; 1172 | } 1173 | for (i = 31; i >= 0; i --) { 1174 | if (z->v[i] != w) { 1175 | int j; 1176 | unsigned x; 1177 | 1178 | x = z->v[i] ^ w; 1179 | for (j = 15; j >= 0; j --) { 1180 | if ((x >> j) != 0) { 1181 | return (i << 4) + j + 1; 1182 | } 1183 | } 1184 | } 1185 | } 1186 | return 0; 1187 | } 1188 | 1189 | static uint64_t 1190 | zint_get_u64(const zint *z) 1191 | { 1192 | return (uint64_t)z->v[0] 1193 | | ((uint64_t)z->v[1] << 16) 1194 | | ((uint64_t)z->v[2] << 32) 1195 | | ((uint64_t)z->v[3] << 48); 1196 | } 1197 | 1198 | static int64_t 1199 | zint_get_s64(const zint *z) 1200 | { 1201 | uint64_t x; 1202 | 1203 | x = zint_get_u64(z); 1204 | return *(int64_t *)&x; 1205 | } 1206 | 1207 | static void 1208 | zint_trunc(zint *z, unsigned bl) 1209 | { 1210 | unsigned k; 1211 | uint16_t w; 1212 | 1213 | if (bl >= 512) { 1214 | return; 1215 | } 1216 | if (bl == 0) { 1217 | memset(z->v, 0, sizeof z->v); 1218 | return; 1219 | } 1220 | bl --; 1221 | k = bl >> 4; 1222 | bl &= 15; 1223 | w = z->v[k]; 1224 | if (((w >> bl) & 1) != 0) { 1225 | z->v[k] |= (0xFFFF << bl) & 0xFFFF; 1226 | for (k ++; k < 32; k ++) { 1227 | z->v[k] = 0xFFFF; 1228 | } 1229 | } else { 1230 | z->v[k] &= ~(0xFFFF << bl); 1231 | for (k ++; k < 32; k ++) { 1232 | z->v[k] = 0x0000; 1233 | } 1234 | } 1235 | } 1236 | 1237 | static void 1238 | zint_copy(zint *d, const zint *s) 1239 | { 1240 | memmove(d->v, s->v, sizeof s->v); 1241 | } 1242 | 1243 | static void 1244 | zint_add(zint *d, const zint *a, const zint *b) 1245 | { 1246 | int i; 1247 | uint32_t cc; 1248 | 1249 | cc = 0; 1250 | for (i = 0; i < 32; i ++) { 1251 | uint32_t wa, wb, wd; 1252 | 1253 | wa = a->v[i]; 1254 | wb = b->v[i]; 1255 | wd = wa + wb + cc; 1256 | cc = wd >> 16; 1257 | d->v[i] = wd & 0xFFFF; 1258 | } 1259 | } 1260 | 1261 | static void 1262 | zint_sub(zint *d, const zint *a, const zint *b) 1263 | { 1264 | int i; 1265 | uint32_t cc; 1266 | 1267 | cc = 0; 1268 | for (i = 0; i < 32; i ++) { 1269 | uint32_t wa, wb, wd; 1270 | 1271 | wa = a->v[i]; 1272 | wb = b->v[i]; 1273 | wd = wa - wb - cc; 1274 | cc = (wd >> 16) & 1; 1275 | d->v[i] = wd & 0xFFFF; 1276 | } 1277 | } 1278 | 1279 | static int 1280 | zint_cmp(const zint *a, const zint *b) 1281 | { 1282 | zint d; 1283 | int i; 1284 | 1285 | zint_sub(&d, a, b); 1286 | if (d.v[31] >= 0x8000) { 1287 | return -1; 1288 | } 1289 | for (i = 0; i < 32; i ++) { 1290 | if (d.v[i] != 0) { 1291 | return 1; 1292 | } 1293 | } 1294 | return 0; 1295 | } 1296 | 1297 | static int 1298 | zint_sign(const zint *a) 1299 | { 1300 | int i; 1301 | 1302 | if (a->v[31] >= 0x8000) { 1303 | return -1; 1304 | } 1305 | for (i = 0; i < 32; i ++) { 1306 | if (a->v[i] != 0) { 1307 | return 1; 1308 | } 1309 | } 1310 | return 0; 1311 | } 1312 | 1313 | static void 1314 | zint_decode(zint *z, const void *src, size_t len, int be, int sig) 1315 | { 1316 | const unsigned char *buf; 1317 | size_t u; 1318 | unsigned bx; 1319 | 1320 | zint_zero(z); 1321 | if (len == 0) { 1322 | return; 1323 | } 1324 | buf = src; 1325 | if (sig) { 1326 | if (be) { 1327 | bx = buf[0] >= 0x80 ? 0xFF : 0x00; 1328 | } else { 1329 | bx = buf[len - 1] >= 0x80 ? 0xFF : 0x00; 1330 | } 1331 | } else { 1332 | bx = 0x00; 1333 | } 1334 | for (u = 0; u < 64; u ++) { 1335 | unsigned b; 1336 | 1337 | if (u < len) { 1338 | b = be ? buf[len - 1 - u] : buf[u]; 1339 | } else { 1340 | b = bx; 1341 | } 1342 | if ((u & 1) != 0) { 1343 | b <<= 8; 1344 | } 1345 | z->v[u >> 1] |= b; 1346 | } 1347 | } 1348 | 1349 | static void 1350 | zint_encode(void *dst, size_t len, const zint *z, int be) 1351 | { 1352 | unsigned char *buf; 1353 | size_t u; 1354 | unsigned ssx; 1355 | 1356 | buf = dst; 1357 | ssx = (z->v[31] >= 0x8000) ? 0xFF : 0x00; 1358 | for (u = 0; u < len; u ++) { 1359 | unsigned b; 1360 | 1361 | if (u < 64) { 1362 | b = z->v[u >> 1]; 1363 | if ((u & 1) != 0) { 1364 | b >>= 8; 1365 | } 1366 | } else { 1367 | b = ssx; 1368 | } 1369 | if (be) { 1370 | buf[len - 1 - u] = b; 1371 | } else { 1372 | buf[u] = b; 1373 | } 1374 | } 1375 | } 1376 | 1377 | static void 1378 | zint_mul(zint *d, zint *a, zint *b) 1379 | { 1380 | zint x, t; 1381 | int i, j; 1382 | 1383 | zint_zero(&t); 1384 | for (i = 0; i < 32; i ++) { 1385 | uint32_t wb, cc; 1386 | 1387 | wb = b->v[i]; 1388 | memset(x.v, 0, i * sizeof(uint16_t)); 1389 | cc = 0; 1390 | for (j = i; j < 32; j ++) { 1391 | uint32_t wa, wx; 1392 | 1393 | wa = a->v[j - i]; 1394 | wx = wa * wb + cc; 1395 | cc = wx >> 16; 1396 | x.v[j] = (uint16_t)wx; 1397 | } 1398 | zint_add(&t, &t, &x); 1399 | } 1400 | zint_copy(d, &t); 1401 | } 1402 | 1403 | static void 1404 | zint_lsh(zint *d, zint *a, unsigned n) 1405 | { 1406 | zint t; 1407 | int i, nd, nm; 1408 | 1409 | nd = (int)(n >> 4); 1410 | nm = (int)(n & 15); 1411 | for (i = 0; i < 32; i ++) { 1412 | if (i < nd) { 1413 | t.v[i] = 0; 1414 | } else if (i == nd) { 1415 | t.v[i] = (uint16_t)((uint32_t)a->v[0] << nm); 1416 | } else { 1417 | t.v[i] = (uint16_t)(((uint32_t)a->v[i - nd] << nm) 1418 | | ((uint32_t)a->v[i - nd - 1] >> (16 - nm))); 1419 | } 1420 | } 1421 | zint_copy(d, &t); 1422 | } 1423 | 1424 | static void 1425 | zint_rsh(zint *d, zint *a, unsigned n) 1426 | { 1427 | int i, nd, nm; 1428 | uint32_t ssa; 1429 | 1430 | nd = (int)(n >> 4); 1431 | nm = (int)(n & 15); 1432 | ssa = (a->v[31] >= 0x8000) ? 0xFFFF : 0x0000; 1433 | for (i = 0; i < 32; i ++) { 1434 | if (i + nd < 31) { 1435 | d->v[i] = (uint16_t)(((uint32_t)a->v[i + nd] >> nm) 1436 | | ((uint32_t)a->v[i + nd + 1] << (16 - nm))); 1437 | } else if (i + nd == 31) { 1438 | d->v[i] = (uint16_t)(((uint32_t)a->v[31] >> nm) 1439 | | (ssa << (16 - nm))); 1440 | } else { 1441 | d->v[i] = ssa; 1442 | } 1443 | } 1444 | } 1445 | 1446 | static void 1447 | zint_and(zint *d, const zint *a, const zint *b) 1448 | { 1449 | int i; 1450 | 1451 | for (i = 0; i < 32; i ++) { 1452 | d->v[i] = a->v[i] & b->v[i]; 1453 | } 1454 | } 1455 | 1456 | static void 1457 | zint_or(zint *d, const zint *a, const zint *b) 1458 | { 1459 | int i; 1460 | 1461 | for (i = 0; i < 32; i ++) { 1462 | d->v[i] = a->v[i] | b->v[i]; 1463 | } 1464 | } 1465 | 1466 | static void 1467 | zint_xor(zint *d, const zint *a, const zint *b) 1468 | { 1469 | int i; 1470 | 1471 | for (i = 0; i < 32; i ++) { 1472 | d->v[i] = a->v[i] ^ b->v[i]; 1473 | } 1474 | } 1475 | 1476 | static void 1477 | zint_eqv(zint *d, const zint *a, const zint *b) 1478 | { 1479 | int i; 1480 | 1481 | for (i = 0; i < 32; i ++) { 1482 | d->v[i] = ~(a->v[i] ^ b->v[i]); 1483 | } 1484 | } 1485 | 1486 | static void 1487 | zint_not(zint *d, const zint *a) 1488 | { 1489 | int i; 1490 | 1491 | for (i = 0; i < 32; i ++) { 1492 | d->v[i] = ~a->v[i]; 1493 | } 1494 | } 1495 | 1496 | static void 1497 | test_i31_set(void) 1498 | { 1499 | cttk_i31_def(x, 500); 1500 | int i, j; 1501 | zint z; 1502 | 1503 | printf("Test i31 set: "); 1504 | fflush(stdout); 1505 | 1506 | rnd_init(1); 1507 | 1508 | for (i = 1; i <= 128; i ++) { 1509 | cttk_i31_init(x, i); 1510 | 1511 | for (j = 0; j < 64; j ++) { 1512 | uint64_t tu64; 1513 | uint32_t tu32; 1514 | 1515 | tu64 = (uint64_t)1 << j; 1516 | cttk_i31_set_u64(x, tu64); 1517 | if (j < (i - 1)) { 1518 | check(cttk_i31_to_u64(x) == tu64, 1519 | "set_u64 1 (%d,%d)", i, j); 1520 | } else { 1521 | check(cttk_i31_to_u64(x) == 0, 1522 | "set_u64 2 (%d,%d)", i, j); 1523 | } 1524 | tu64 = (tu64 << 1) - 1; 1525 | cttk_i31_set_u64(x, tu64); 1526 | if (j < (i - 1)) { 1527 | check(cttk_i31_to_u64(x) == tu64, 1528 | "set_u64 3 (%d,%d)", i, j); 1529 | } else { 1530 | check(cttk_i31_to_u64(x) == 0, 1531 | "set_u64 4 (%d,%d)", i, j); 1532 | } 1533 | cttk_i31_set_u64_trunc(x, tu64); 1534 | if (j < (i - 1)) { 1535 | check(cttk_i31_to_u64_trunc(x) == tu64, 1536 | "set_u64 5 (%d,%d)", i, j); 1537 | } else { 1538 | check(cttk_i31_to_u64_trunc(x) == (uint64_t)-1, 1539 | "set_u64 6 (%d,%d)", i, j); 1540 | } 1541 | 1542 | if (j >= 32) { 1543 | continue; 1544 | } 1545 | 1546 | tu32 = (uint32_t)1 << j; 1547 | cttk_i31_set_u32(x, tu32); 1548 | if (j < (i - 1)) { 1549 | check(cttk_i31_to_u32(x) == tu32, 1550 | "set_u32 1 (%d,%d)", i, j); 1551 | } else { 1552 | check(cttk_i31_to_u32(x) == 0, 1553 | "set_u32 2 (%d,%d)", i, j); 1554 | } 1555 | tu32 = (tu32 << 1) - 1; 1556 | cttk_i31_set_u32(x, tu32); 1557 | if (j < (i - 1)) { 1558 | check(cttk_i31_to_u32(x) == tu32, 1559 | "set_u32 3 (%d,%d)", i, j); 1560 | } else { 1561 | check(cttk_i31_to_u32(x) == 0, 1562 | "set_u32 4 (%d,%d)", i, j); 1563 | } 1564 | cttk_i31_set_u32_trunc(x, tu32); 1565 | if (j < (i - 1)) { 1566 | check(cttk_i31_to_u32_trunc(x) == tu32, 1567 | "set_u32 5 (%d,%d)", i, j); 1568 | } else { 1569 | check(cttk_i31_to_u32_trunc(x) == (uint32_t)-1, 1570 | "set_u32 6 (%d,%d)", i, j); 1571 | } 1572 | } 1573 | 1574 | for (j = 0; j < 100; j ++) { 1575 | uint64_t tu64; 1576 | uint32_t tu32; 1577 | int64_t ts64; 1578 | int32_t ts32; 1579 | 1580 | tu64 = rnd64(); 1581 | ts64 = *(int64_t *)&tu64; 1582 | tu32 = rnd32(); 1583 | ts32 = *(int32_t *)&tu32; 1584 | 1585 | cttk_i31_set_u64_trunc(x, tu64); 1586 | zint_set_u64(&z, tu64); 1587 | zint_trunc(&z, i); 1588 | if (i <= 64 && zint_get_s64(&z) < 0) { 1589 | check(cttk_i31_to_u64(x) == 0, 1590 | "to_u64 1 (%d,%d)", i, j); 1591 | } else { 1592 | check(cttk_i31_to_u64(x) == zint_get_u64(&z), 1593 | "to_u64 2 (%d,%d)", i, j); 1594 | } 1595 | if (i >= 65 && tu64 >= ((uint64_t)1 << 63)) { 1596 | check(cttk_i31_to_s64(x) == 0, 1597 | "to_s64 1 (%d,%d)", i, j); 1598 | check(cttk_i31_to_s64_trunc(x) == ts64, 1599 | "to_s64_trunc 1 (%d,%d)", i, j); 1600 | check(cttk_i31_to_u64_trunc(x) == tu64, 1601 | "to_u64_trunc 1 (%d,%d)", i, j); 1602 | } else { 1603 | check(cttk_i31_to_s64(x) == zint_get_s64(&z), 1604 | "to_s64 2 (%d,%d)", i, j); 1605 | check(cttk_i31_to_s64_trunc(x) 1606 | == zint_get_s64(&z), 1607 | "to_s64_trunc 2 (%d,%d)", i, j); 1608 | check(cttk_i31_to_u64_trunc(x) 1609 | == zint_get_u64(&z), 1610 | "to_u64_trunc 2 (%d,%d)", i, j); 1611 | } 1612 | 1613 | cttk_i31_set_u32_trunc(x, tu32); 1614 | zint_set_u64(&z, tu32); 1615 | zint_trunc(&z, i); 1616 | if (zint_get_s64(&z) < 0) { 1617 | check(cttk_i31_to_u32(x) == 0, 1618 | "to_u32 1 (%d,%d)", i, j); 1619 | } else { 1620 | check(cttk_i31_to_u32(x) == zint_get_u64(&z), 1621 | "to_u32 2 (%d,%d)", i, j); 1622 | } 1623 | if (i >= 33 && tu32 >= ((uint32_t)1 << 31)) { 1624 | check(cttk_i31_to_s32(x) == 0, 1625 | "to_s32 1 (%d,%d)", i, j); 1626 | check(cttk_i31_to_s32_trunc(x) == ts32, 1627 | "to_s32_trunc 1 (%d,%d)", i, j); 1628 | check(cttk_i31_to_u32_trunc(x) == tu32, 1629 | "to_u32_trunc 1 (%d,%d)", i, j); 1630 | } else { 1631 | check(cttk_i31_to_s32(x) == zint_get_s64(&z), 1632 | "to_s32 2 (%d,%d)", i, j); 1633 | check(cttk_i31_to_s32_trunc(x) 1634 | == zint_get_s64(&z), 1635 | "to_s32_trunc 2 (%d,%d)", i, j); 1636 | check(cttk_i31_to_u32_trunc(x) 1637 | == (uint32_t)zint_get_u64(&z), 1638 | "to_u32_trunc 2 (%d,%d)", i, j); 1639 | } 1640 | } 1641 | 1642 | if ((i & 7) == 0) { 1643 | printf("."); 1644 | fflush(stdout); 1645 | } 1646 | } 1647 | 1648 | printf(" "); 1649 | fflush(stdout); 1650 | 1651 | for (i = 1; i <= 80; i ++) { 1652 | for (j = 1; j <= 80; j ++) { 1653 | int k; 1654 | 1655 | for (k = 0; k < 10; k ++) { 1656 | unsigned char tmp[17], tmp2[17]; 1657 | cttk_i31_def(x, 100); 1658 | cttk_i31_def(y, 100); 1659 | 1660 | cttk_i31_init(x, i); 1661 | cttk_i31_init(y, j); 1662 | rnd(tmp, 17); 1663 | zint_decode(&z, tmp, 17, 0, 0); 1664 | zint_trunc(&z, i); 1665 | zint_encode(tmp, 17, &z, 0); 1666 | cttk_i31_decle_signed(x, tmp, 17); 1667 | 1668 | cttk_i31_set(y, x); 1669 | if (zint_bitlength(&z) >= (unsigned)j) { 1670 | check(cttk_i31_isnan(y).v, 1671 | "set 1 (%d,%d,%d)", i, j, k); 1672 | } else { 1673 | check(!cttk_i31_isnan(y).v, 1674 | "set 2 (%d,%d,%d)", i, j, k); 1675 | cttk_i31_encle(tmp2, 17, y); 1676 | check(memcmp(tmp, tmp2, 17) == 0, 1677 | "set 3 (%d,%d,%d)", i, j, k); 1678 | } 1679 | 1680 | cttk_i31_set_trunc(y, x); 1681 | cttk_i31_encle(tmp2, 17, y); 1682 | zint_trunc(&z, j); 1683 | zint_encode(tmp, 17, &z, 0); 1684 | check(!cttk_i31_isnan(y).v, 1685 | "set 4 (%d,%d,%d)", i, j, k); 1686 | check(memcmp(tmp, tmp2, 17) == 0, 1687 | "set 5 (%d,%d,%d)", i, j, k); 1688 | } 1689 | } 1690 | 1691 | if ((i & 3) == 0) { 1692 | printf("."); 1693 | fflush(stdout); 1694 | } 1695 | } 1696 | 1697 | printf(" done.\n"); 1698 | fflush(stdout); 1699 | } 1700 | 1701 | static int 1702 | memiszero(const void *data, size_t len) 1703 | { 1704 | unsigned x; 1705 | const unsigned char *buf; 1706 | 1707 | buf = data; 1708 | x = 0; 1709 | while (len -- > 0) { 1710 | x |= *buf ++; 1711 | } 1712 | return x == 0; 1713 | } 1714 | 1715 | static void 1716 | test_i31_codec(void) 1717 | { 1718 | cttk_i31_def(x, 300); 1719 | zint z; 1720 | int i, j, be; 1721 | unsigned char tmp1[100], tmp2[100]; 1722 | 1723 | printf("Test i31 codec: "); 1724 | fflush(stdout); 1725 | 1726 | rnd_init(3); 1727 | 1728 | for (be = 0; be < 2; be ++) { 1729 | for (i = 1; i <= 128; i ++) { 1730 | cttk_i31_init(x, i); 1731 | 1732 | for (j = 0; j < 100; j ++) { 1733 | rnd(tmp1, 17); 1734 | zint_decode(&z, tmp1, 17, be, 0); 1735 | zint_trunc(&z, i + 2); 1736 | zint_encode(tmp1, 17, &z, be); 1737 | 1738 | if (be) { 1739 | cttk_i31_decbe_signed(x, tmp1, 17); 1740 | cttk_i31_encbe(tmp2, 17, x); 1741 | } else { 1742 | cttk_i31_decle_signed(x, tmp1, 17); 1743 | cttk_i31_encle(tmp2, 17, x); 1744 | } 1745 | if (zint_bitlength(&z) < (unsigned)i) { 1746 | check(memcmp(tmp2, tmp1, 17) == 0, 1747 | "codec 1 (%d,%d,%d)", be, i, j); 1748 | } else { 1749 | check(cttk_bool_to_int( 1750 | cttk_i31_isnan(x)), 1751 | "codec 2 (%d,%d,%d)", be, i, j); 1752 | check(memiszero(tmp2, 17), 1753 | "codec 3 (%d,%d,%d)", be, i, j); 1754 | } 1755 | if (be) { 1756 | cttk_i31_decbe_unsigned(x, tmp1, 17); 1757 | cttk_i31_encbe(tmp2, 17, x); 1758 | } else { 1759 | cttk_i31_decle_unsigned(x, tmp1, 17); 1760 | cttk_i31_encle(tmp2, 17, x); 1761 | } 1762 | if (zint_bitlength(&z) < (unsigned)i 1763 | && z.v[31] < 0x8000) 1764 | { 1765 | check(memcmp(tmp2, tmp1, 17) == 0, 1766 | "codec 4 (%d,%d,%d)", be, i, j); 1767 | } else { 1768 | check(cttk_bool_to_int( 1769 | cttk_i31_isnan(x)), 1770 | "codec 5 (%d,%d,%d)", be, i, j); 1771 | check(memiszero(tmp2, 17), 1772 | "codec 6 (%d,%d,%d)", be, i, j); 1773 | } 1774 | 1775 | rnd(tmp1, 17); 1776 | if (be) { 1777 | cttk_i31_decbe_signed_trunc( 1778 | x, tmp1, 17); 1779 | cttk_i31_encbe(tmp2, 17, x); 1780 | } else { 1781 | cttk_i31_decle_signed_trunc( 1782 | x, tmp1, 17); 1783 | cttk_i31_encle(tmp2, 17, x); 1784 | } 1785 | zint_decode(&z, tmp1, 17, be, 0); 1786 | zint_trunc(&z, i); 1787 | zint_encode(tmp1, 17, &z, be); 1788 | check(memcmp(tmp1, tmp2, 17) == 0, 1789 | "codec 7 (%d,%d,%d)", be, i, j); 1790 | 1791 | rnd(tmp1, 8); 1792 | if (be) { 1793 | cttk_i31_decbe_unsigned_trunc( 1794 | x, tmp1, 8); 1795 | cttk_i31_encbe(tmp2, 17, x); 1796 | } else { 1797 | cttk_i31_decle_unsigned_trunc( 1798 | x, tmp1, 8); 1799 | cttk_i31_encle(tmp2, 17, x); 1800 | } 1801 | zint_decode(&z, tmp1, 8, be, 0); 1802 | zint_trunc(&z, i); 1803 | zint_encode(tmp1, 17, &z, be); 1804 | check(memcmp(tmp1, tmp2, 17) == 0, 1805 | "codec 8 (%d,%d,%d)", be, i, j); 1806 | } 1807 | 1808 | if ((i & 7) == 0) { 1809 | printf("."); 1810 | fflush(stdout); 1811 | } 1812 | } 1813 | } 1814 | 1815 | printf(" done.\n"); 1816 | fflush(stdout); 1817 | } 1818 | 1819 | static void 1820 | test_i31_cmp(void) 1821 | { 1822 | cttk_i31_def(x1, 300); 1823 | cttk_i31_def(x2, 300); 1824 | zint z1, z2; 1825 | int i, j; 1826 | unsigned char tmp1[100], tmp2[100]; 1827 | 1828 | printf("Test i31 codec: "); 1829 | fflush(stdout); 1830 | 1831 | rnd_init(4); 1832 | 1833 | for (i = 1; i <= 128; i ++) { 1834 | cttk_i31_init(x1, i); 1835 | cttk_i31_init(x2, i); 1836 | 1837 | check(!cttk_bool_to_int(cttk_i31_eq0(x1)), 1838 | "cmp nan1 1 (%d)", i); 1839 | check(!cttk_bool_to_int(cttk_i31_neq0(x1)), 1840 | "cmp nan1 2 (%d)", i); 1841 | check(!cttk_bool_to_int(cttk_i31_lt0(x1)), 1842 | "cmp nan1 3 (%d)", i); 1843 | check(!cttk_bool_to_int(cttk_i31_leq0(x1)), 1844 | "cmp nan1 4 (%d)", i); 1845 | check(!cttk_bool_to_int(cttk_i31_gt0(x1)), 1846 | "cmp nan1 5 (%d)", i); 1847 | check(!cttk_bool_to_int(cttk_i31_geq0(x1)), 1848 | "cmp nan1 6 (%d)", i); 1849 | check(!cttk_bool_to_int(cttk_i31_eq(x1, x2)), 1850 | "cmp nan1 7 (%d)", i); 1851 | check(!cttk_bool_to_int(cttk_i31_neq(x1, x2)), 1852 | "cmp nan1 8 (%d)", i); 1853 | check(!cttk_bool_to_int(cttk_i31_lt(x1, x2)), 1854 | "cmp nan1 9 (%d)", i); 1855 | check(!cttk_bool_to_int(cttk_i31_leq(x1, x2)), 1856 | "cmp nan1 10 (%d)", i); 1857 | check(!cttk_bool_to_int(cttk_i31_gt(x1, x2)), 1858 | "cmp nan1 11 (%d)", i); 1859 | check(!cttk_bool_to_int(cttk_i31_geq(x1, x2)), 1860 | "cmp nan1 12 (%d)", i); 1861 | 1862 | cttk_i31_set_s32(x1, 0); 1863 | check(cttk_bool_to_int(cttk_i31_eq0(x1)), 1864 | "cmp eq0 1 (%d)", i); 1865 | check(!cttk_bool_to_int(cttk_i31_neq0(x1)), 1866 | "cmp neq0 2 (%d)", i); 1867 | check(!cttk_bool_to_int(cttk_i31_lt0(x1)), 1868 | "cmp lt0 3 (%d)", i); 1869 | check(cttk_bool_to_int(cttk_i31_leq0(x1)), 1870 | "cmp leq0 4 (%d)", i); 1871 | check(!cttk_bool_to_int(cttk_i31_gt0(x1)), 1872 | "cmp gt0 5 (%d)", i); 1873 | check(cttk_bool_to_int(cttk_i31_geq0(x1)), 1874 | "cmp geq0 6 (%d)", i); 1875 | check(!cttk_bool_to_int(cttk_i31_eq(x1, x2)), 1876 | "cmp nan2 1 (%d)", i); 1877 | check(!cttk_bool_to_int(cttk_i31_neq(x1, x2)), 1878 | "cmp nan2 2 (%d)", i); 1879 | check(!cttk_bool_to_int(cttk_i31_lt(x1, x2)), 1880 | "cmp nan2 3 (%d)", i); 1881 | check(!cttk_bool_to_int(cttk_i31_leq(x1, x2)), 1882 | "cmp nan2 4 (%d)", i); 1883 | check(!cttk_bool_to_int(cttk_i31_gt(x1, x2)), 1884 | "cmp nan2 5 (%d)", i); 1885 | check(!cttk_bool_to_int(cttk_i31_geq(x1, x2)), 1886 | "cmp nan2 6 (%d)", i); 1887 | check(!cttk_bool_to_int(cttk_i31_eq(x2, x1)), 1888 | "cmp nan2 7 (%d)", i); 1889 | check(!cttk_bool_to_int(cttk_i31_neq(x2, x1)), 1890 | "cmp nan2 8 (%d)", i); 1891 | check(!cttk_bool_to_int(cttk_i31_lt(x2, x1)), 1892 | "cmp nan2 9 (%d)", i); 1893 | check(!cttk_bool_to_int(cttk_i31_leq(x2, x1)), 1894 | "cmp nan2 10 (%d)", i); 1895 | check(!cttk_bool_to_int(cttk_i31_gt(x2, x1)), 1896 | "cmp nan2 11 (%d)", i); 1897 | check(!cttk_bool_to_int(cttk_i31_geq(x2, x1)), 1898 | "cmp nan2 12 (%d)", i); 1899 | 1900 | for (j = 0; j < 100; j ++) { 1901 | int cc; 1902 | 1903 | rnd(tmp1, 17); 1904 | rnd(tmp2, 17); 1905 | zint_decode(&z1, tmp1, 17, 0, 0); 1906 | zint_decode(&z2, tmp2, 17, 0, 0); 1907 | zint_trunc(&z1, i); 1908 | zint_trunc(&z2, i); 1909 | zint_encode(tmp1, 17, &z1, 0); 1910 | zint_encode(tmp2, 17, &z2, 0); 1911 | cttk_i31_decle_signed(x1, tmp1, 17); 1912 | cttk_i31_decle_signed(x2, tmp2, 17); 1913 | 1914 | cc = zint_cmp(&z1, &z2); 1915 | check(cttk_i31_cmp(x1, x2) == cc, 1916 | "cmp 1 (%d,%d)", i, j); 1917 | check(cttk_bool_to_int(cttk_i31_lt(x1, x2)) 1918 | == (cc < 0), "cmp 2 (%d,%d)", i, j); 1919 | check(cttk_bool_to_int(cttk_i31_leq(x1, x2)) 1920 | == (cc <= 0), "cmp 3 (%d,%d)", i, j); 1921 | check(cttk_bool_to_int(cttk_i31_gt(x1, x2)) 1922 | == (cc > 0), "cmp 4 (%d,%d)", i, j); 1923 | check(cttk_bool_to_int(cttk_i31_geq(x1, x2)) 1924 | == (cc >= 0), "cmp 5 (%d,%d)", i, j); 1925 | check(cttk_bool_to_int(cttk_i31_eq(x1, x1)), 1926 | "cmp 6 (%d,%d)", i, j); 1927 | check(cttk_bool_to_int(cttk_i31_geq(x1, x1)), 1928 | "cmp 7 (%d,%d)", i, j); 1929 | check(cttk_bool_to_int(cttk_i31_leq(x1, x1)), 1930 | "cmp 8 (%d,%d)", i, j); 1931 | check(!cttk_bool_to_int(cttk_i31_neq(x1, x1)), 1932 | "cmp 9 (%d,%d)", i, j); 1933 | check(!cttk_bool_to_int(cttk_i31_gt(x1, x1)), 1934 | "cmp 10 (%d,%d)", i, j); 1935 | check(!cttk_bool_to_int(cttk_i31_lt(x1, x1)), 1936 | "cmp 11 (%d,%d)", i, j); 1937 | 1938 | cc = zint_sign(&z1); 1939 | check(cttk_bool_to_int(cttk_i31_lt0(x1)) == (cc < 0), 1940 | "cmp 12 (%d,%d)", i, j); 1941 | check(cttk_bool_to_int(cttk_i31_leq0(x1)) == (cc <= 0), 1942 | "cmp 13 (%d,%d)", i, j); 1943 | check(cttk_bool_to_int(cttk_i31_gt0(x1)) == (cc > 0), 1944 | "cmp 14 (%d,%d)", i, j); 1945 | check(cttk_bool_to_int(cttk_i31_geq0(x1)) == (cc >= 0), 1946 | "cmp 15 (%d,%d)", i, j); 1947 | } 1948 | 1949 | if ((i & 3) == 0) { 1950 | printf("."); 1951 | fflush(stdout); 1952 | } 1953 | } 1954 | 1955 | printf(" done.\n"); 1956 | fflush(stdout); 1957 | } 1958 | 1959 | static void 1960 | test_i31_addsub(void) 1961 | { 1962 | cttk_i31_def(x1, 300); 1963 | cttk_i31_def(x2, 300); 1964 | cttk_i31_def(x3, 300); 1965 | zint z1, z2, z3; 1966 | int i, j; 1967 | unsigned char tmp1[100], tmp2[100], tmp3[100], tmp4[100]; 1968 | 1969 | printf("Test i31 add/sub: "); 1970 | fflush(stdout); 1971 | 1972 | rnd_init(5); 1973 | 1974 | for (i = 1; i <= 128; i ++) { 1975 | cttk_i31_init(x1, i); 1976 | cttk_i31_init(x2, i); 1977 | cttk_i31_init(x3, i); 1978 | 1979 | for (j = 0; j < 100; j ++) { 1980 | rnd(tmp1, 17); 1981 | rnd(tmp2, 17); 1982 | zint_decode(&z1, tmp1, 17, 0, 0); 1983 | zint_decode(&z2, tmp2, 17, 0, 0); 1984 | zint_trunc(&z1, i); 1985 | zint_trunc(&z2, i); 1986 | zint_encode(tmp1, 17, &z1, 0); 1987 | zint_encode(tmp2, 17, &z2, 0); 1988 | cttk_i31_decle_signed(x1, tmp1, 17); 1989 | cttk_i31_decle_signed(x2, tmp2, 17); 1990 | 1991 | zint_add(&z3, &z1, &z2); 1992 | zint_encode(tmp3, 17, &z3, 0); 1993 | cttk_i31_add(x3, x1, x2); 1994 | if (zint_bitlength(&z3) >= (uint32_t)i) { 1995 | check(cttk_bool_to_int(cttk_i31_isnan(x3)), 1996 | "add 1 (%d,%d)", i, j); 1997 | } else { 1998 | cttk_i31_encle(tmp4, 17, x3); 1999 | check(memcmp(tmp3, tmp4, 17) == 0, 2000 | "add 2 (%d,%d)", i, j); 2001 | } 2002 | zint_trunc(&z3, i); 2003 | zint_encode(tmp3, 17, &z3, 0); 2004 | cttk_i31_add_trunc(x3, x1, x2); 2005 | cttk_i31_encle(tmp4, 17, x3); 2006 | check(memcmp(tmp3, tmp4, 17) == 0, 2007 | "add 3 (%d,%d)", i, j); 2008 | 2009 | zint_sub(&z3, &z1, &z2); 2010 | zint_encode(tmp3, 17, &z3, 0); 2011 | cttk_i31_sub(x3, x1, x2); 2012 | if (zint_bitlength(&z3) >= (uint32_t)i) { 2013 | check(cttk_bool_to_int(cttk_i31_isnan(x3)), 2014 | "sub 1 (%d,%d)", i, j); 2015 | } else { 2016 | cttk_i31_encle(tmp4, 17, x3); 2017 | check(memcmp(tmp3, tmp4, 17) == 0, 2018 | "sub 2 (%d,%d)", i, j); 2019 | } 2020 | zint_trunc(&z3, i); 2021 | zint_encode(tmp3, 17, &z3, 0); 2022 | cttk_i31_sub_trunc(x3, x1, x2); 2023 | cttk_i31_encle(tmp4, 17, x3); 2024 | check(memcmp(tmp3, tmp4, 17) == 0, 2025 | "sub 3 (%d,%d)", i, j); 2026 | 2027 | zint_zero(&z1); 2028 | zint_sub(&z3, &z1, &z2); 2029 | zint_encode(tmp3, 17, &z3, 0); 2030 | cttk_i31_neg(x3, x2); 2031 | if (zint_bitlength(&z3) >= (uint32_t)i) { 2032 | check(cttk_bool_to_int(cttk_i31_isnan(x3)), 2033 | "neg 1 (%d,%d)", i, j); 2034 | } else { 2035 | cttk_i31_encle(tmp4, 17, x3); 2036 | check(memcmp(tmp3, tmp4, 17) == 0, 2037 | "neg 2 (%d,%d)", i, j); 2038 | } 2039 | zint_trunc(&z3, i); 2040 | zint_encode(tmp3, 17, &z3, 0); 2041 | cttk_i31_neg_trunc(x3, x2); 2042 | cttk_i31_encle(tmp4, 17, x3); 2043 | check(memcmp(tmp3, tmp4, 17) == 0, 2044 | "neg 3 (%d,%d)", i, j); 2045 | } 2046 | 2047 | memset(tmp1, 0, 17); 2048 | tmp1[(i - 1) >> 3] |= 1 << ((i - 1) & 7); 2049 | cttk_i31_decle_unsigned_trunc(x1, tmp1, 17); 2050 | check(cttk_bool_to_int(cttk_i31_lt0(x1)), 2051 | "negmin 1 (%d)", i); 2052 | cttk_i31_neg(x3, x1); 2053 | check(cttk_bool_to_int(cttk_i31_isnan(x3)), 2054 | "negmin 2 (%d)", i); 2055 | cttk_i31_neg_trunc(x3, x1); 2056 | check(!cttk_bool_to_int(cttk_i31_isnan(x3)), 2057 | "negmin 3 (%d)", i); 2058 | check(cttk_bool_to_int(cttk_i31_eq(x1, x3)), 2059 | "negmin 4 (%d)", i); 2060 | 2061 | if ((i & 3) == 0) { 2062 | printf("."); 2063 | fflush(stdout); 2064 | } 2065 | } 2066 | 2067 | printf(" done.\n"); 2068 | fflush(stdout); 2069 | } 2070 | 2071 | static void 2072 | test_i31_mul(void) 2073 | { 2074 | cttk_i31_def(x1, 300); 2075 | cttk_i31_def(x2, 300); 2076 | cttk_i31_def(x3, 300); 2077 | zint z1, z2, z3; 2078 | int i, j; 2079 | unsigned char tmp1[100], tmp2[100], tmp3[100], tmp4[100]; 2080 | 2081 | printf("Test i31 mul: "); 2082 | fflush(stdout); 2083 | 2084 | rnd_init(6); 2085 | 2086 | cttk_i31_init(x1, 1); 2087 | cttk_i31_init(x2, 1); 2088 | cttk_i31_init(x3, 1); 2089 | cttk_i31_set_s32(x1, 0); 2090 | cttk_i31_set_s32(x2, -1); 2091 | cttk_i31_mul(x3, x1, x2); 2092 | check(!cttk_bool_to_int(cttk_i31_isnan(x3)), "mul0-1"); 2093 | check(cttk_i31_to_s32(x3) == 0, "mul0-2"); 2094 | cttk_i31_mul(x3, x2, x1); 2095 | check(!cttk_bool_to_int(cttk_i31_isnan(x3)), "mul0-3"); 2096 | check(cttk_i31_to_s32(x3) == 0, "mul0-4"); 2097 | 2098 | for (i = 1; i <= 128; i ++) { 2099 | cttk_i31_init(x1, i); 2100 | cttk_i31_init(x2, i); 2101 | cttk_i31_init(x3, i); 2102 | 2103 | for (j = 0; j < 1000; j ++) { 2104 | rnd(tmp1, 17); 2105 | rnd(tmp2, 17); 2106 | zint_decode(&z1, tmp1, 17, 0, 0); 2107 | zint_decode(&z2, tmp2, 17, 0, 0); 2108 | zint_trunc(&z1, i); 2109 | zint_trunc(&z2, i); 2110 | zint_encode(tmp1, 17, &z1, 0); 2111 | zint_encode(tmp2, 17, &z2, 0); 2112 | cttk_i31_decle_signed(x1, tmp1, 17); 2113 | cttk_i31_decle_signed(x2, tmp2, 17); 2114 | 2115 | zint_mul(&z3, &z1, &z2); 2116 | zint_encode(tmp3, 17, &z3, 0); 2117 | cttk_i31_mul(x3, x1, x2); 2118 | if (zint_bitlength(&z3) >= (uint32_t)i) { 2119 | check(cttk_bool_to_int(cttk_i31_isnan(x3)), 2120 | "mul 1 (%d,%d)", i, j); 2121 | } else { 2122 | check(!cttk_bool_to_int(cttk_i31_isnan(x3)), 2123 | "mul 2 (%d,%d)", i, j); 2124 | cttk_i31_encle(tmp4, 17, x3); 2125 | check(memcmp(tmp3, tmp4, 17) == 0, 2126 | "mul 3 (%d,%d)", i, j); 2127 | } 2128 | zint_trunc(&z3, i); 2129 | zint_encode(tmp3, 17, &z3, 0); 2130 | cttk_i31_mul_trunc(x3, x1, x2); 2131 | cttk_i31_encle(tmp4, 17, x3); 2132 | check(!cttk_bool_to_int(cttk_i31_isnan(x3)), 2133 | "mul 4 (%d,%d)", i, j); 2134 | check(memcmp(tmp3, tmp4, 17) == 0, 2135 | "mul 5 (%d,%d)", i, j); 2136 | 2137 | rnd(tmp1, 17); 2138 | rnd(tmp2, 17); 2139 | zint_decode(&z1, tmp1, 17, 0, 0); 2140 | zint_decode(&z2, tmp2, 17, 0, 0); 2141 | zint_trunc(&z1, (i + 2) >> 1); 2142 | zint_trunc(&z2, (i + 2) >> 1); 2143 | zint_encode(tmp1, 17, &z1, 0); 2144 | zint_encode(tmp2, 17, &z2, 0); 2145 | cttk_i31_decle_signed(x1, tmp1, 17); 2146 | cttk_i31_decle_signed(x2, tmp2, 17); 2147 | 2148 | zint_mul(&z3, &z1, &z2); 2149 | zint_encode(tmp3, 17, &z3, 0); 2150 | cttk_i31_mul(x3, x1, x2); 2151 | if (zint_bitlength(&z3) >= (uint32_t)i) { 2152 | check(cttk_bool_to_int(cttk_i31_isnan(x3)), 2153 | "mul 6 (%d,%d)", i, j); 2154 | } else { 2155 | check(!cttk_bool_to_int(cttk_i31_isnan(x3)), 2156 | "mul 7 (%d,%d)", i, j); 2157 | cttk_i31_encle(tmp4, 17, x3); 2158 | check(memcmp(tmp3, tmp4, 17) == 0, 2159 | "mul 8 (%d,%d)", i, j); 2160 | } 2161 | zint_trunc(&z3, i); 2162 | zint_encode(tmp3, 17, &z3, 0); 2163 | cttk_i31_mul_trunc(x3, x1, x2); 2164 | cttk_i31_encle(tmp4, 17, x3); 2165 | check(!cttk_bool_to_int(cttk_i31_isnan(x3)), 2166 | "mul 9 (%d,%d)", i, j); 2167 | check(memcmp(tmp3, tmp4, 17) == 0, 2168 | "mul 10 (%d,%d)", i, j); 2169 | 2170 | cttk_i31_mul_trunc(x1, x1, x2); 2171 | cttk_i31_encle(tmp4, 17, x1); 2172 | check(!cttk_bool_to_int(cttk_i31_isnan(x1)), 2173 | "mul 11 (%d,%d)", i, j); 2174 | check(memcmp(tmp3, tmp4, 17) == 0, 2175 | "mul 12 (%d,%d)", i, j); 2176 | } 2177 | 2178 | memset(tmp1, 0, 17); 2179 | for (j = i - 1; j < 17 * 8; j ++) { 2180 | tmp1[j >> 3] |= 1 << (j & 7); 2181 | } 2182 | memset(tmp2, 0xFF, 17); 2183 | cttk_i31_decle_signed(x1, tmp1, 17); 2184 | cttk_i31_decle_signed(x2, tmp2, 17); 2185 | check(!cttk_bool_to_int(cttk_i31_isnan(x1)), "mul 13 (%d)", i); 2186 | check(!cttk_bool_to_int(cttk_i31_isnan(x2)), "mul 14 (%d)", i); 2187 | cttk_i31_mul(x3, x1, x2); 2188 | check(cttk_bool_to_int(cttk_i31_isnan(x3)), "mul 15 (%d)", i); 2189 | cttk_i31_mul_trunc(x3, x1, x2); 2190 | check(!cttk_bool_to_int(cttk_i31_isnan(x3)), "mul 16 (%d)", i); 2191 | check(cttk_bool_to_int(cttk_i31_eq(x3, x1)), "mul 17 (%d)", i); 2192 | 2193 | if ((i & 3) == 0) { 2194 | printf("."); 2195 | fflush(stdout); 2196 | } 2197 | } 2198 | 2199 | printf(" done.\n"); 2200 | fflush(stdout); 2201 | } 2202 | 2203 | static void 2204 | test_i31_shift(void) 2205 | { 2206 | cttk_i31_def(x1, 300); 2207 | cttk_i31_def(x2, 300); 2208 | zint z1, z2; 2209 | int i, j, k; 2210 | unsigned char tmp1[100], tmp2[100], tmp3[100]; 2211 | 2212 | printf("Test i31 shift: "); 2213 | fflush(stdout); 2214 | 2215 | rnd_init(7); 2216 | 2217 | for (i = 1; i <= 128; i ++) { 2218 | cttk_i31_init(x1, i); 2219 | cttk_i31_init(x2, i); 2220 | 2221 | for (j = 0; j <= i + 32; j ++) { 2222 | for (k = 0; k < 50; k ++) { 2223 | rnd(tmp1, 17); 2224 | zint_decode(&z1, tmp1, 17, 0, 0); 2225 | zint_trunc(&z1, i); 2226 | zint_encode(tmp1, 17, &z1, 0); 2227 | cttk_i31_decle_signed(x1, tmp1, 17); 2228 | 2229 | zint_lsh(&z2, &z1, j); 2230 | zint_encode(tmp2, 17, &z2, 0); 2231 | cttk_i31_lsh(x2, x1, j); 2232 | if (zint_bitlength(&z2) >= (uint32_t)i) { 2233 | check(cttk_bool_to_int( 2234 | cttk_i31_isnan(x2)), 2235 | "lsh 1 (%d,%d,%d)", i, j, k); 2236 | } else { 2237 | check(!cttk_bool_to_int( 2238 | cttk_i31_isnan(x2)), 2239 | "lsh 2 (%d,%d,%d)", i, j, k); 2240 | cttk_i31_encle(tmp3, 17, x2); 2241 | check(memcmp(tmp2, tmp3, 17) == 0, 2242 | "lsh 3 (%d,%d,%d)", i, j, k); 2243 | } 2244 | 2245 | cttk_i31_lsh_prot(x2, x1, j); 2246 | if (zint_bitlength(&z2) >= (uint32_t)i) { 2247 | check(cttk_bool_to_int( 2248 | cttk_i31_isnan(x2)), 2249 | "lsh 4 (%d,%d,%d)", i, j, k); 2250 | } else { 2251 | check(!cttk_bool_to_int( 2252 | cttk_i31_isnan(x2)), 2253 | "lsh 5 (%d,%d,%d)", i, j, k); 2254 | cttk_i31_encle(tmp3, 17, x2); 2255 | check(memcmp(tmp2, tmp3, 17) == 0, 2256 | "lsh 6 (%d,%d,%d)", i, j, k); 2257 | } 2258 | 2259 | zint_trunc(&z2, i); 2260 | zint_encode(tmp2, 17, &z2, 0); 2261 | cttk_i31_lsh_trunc(x2, x1, j); 2262 | cttk_i31_encle(tmp3, 17, x2); 2263 | check(memcmp(tmp2, tmp3, 17) == 0, 2264 | "lsh 7 (%d,%d,%d)", i, j, k); 2265 | cttk_i31_lsh_trunc_prot(x2, x1, j); 2266 | cttk_i31_encle(tmp3, 17, x2); 2267 | check(memcmp(tmp2, tmp3, 17) == 0, 2268 | "lsh 8 (%d,%d,%d)", i, j, k); 2269 | 2270 | zint_rsh(&z2, &z1, j); 2271 | zint_encode(tmp2, 17, &z2, 0); 2272 | cttk_i31_rsh(x2, x1, j); 2273 | cttk_i31_encle(tmp3, 17, x2); 2274 | check(memcmp(tmp2, tmp3, 17) == 0, 2275 | "rsh 1 (%d,%d,%d)", i, j, k); 2276 | cttk_i31_rsh_prot(x2, x1, j); 2277 | cttk_i31_encle(tmp3, 17, x2); 2278 | check(memcmp(tmp2, tmp3, 17) == 0, 2279 | "rsh 2 (%d,%d,%d)", i, j, k); 2280 | } 2281 | } 2282 | 2283 | if ((i & 3) == 0) { 2284 | printf("."); 2285 | fflush(stdout); 2286 | } 2287 | } 2288 | 2289 | printf(" done.\n"); 2290 | fflush(stdout); 2291 | } 2292 | 2293 | static void 2294 | test_i31_div(void) 2295 | { 2296 | cttk_i31_def(a, 300); 2297 | cttk_i31_def(b, 300); 2298 | cttk_i31_def(q, 300); 2299 | cttk_i31_def(r, 300); 2300 | cttk_i31_def(m, 300); 2301 | cttk_i31_def(x, 300); 2302 | int i, j; 2303 | unsigned char tmp1[100], tmp2[100]; 2304 | 2305 | printf("Test i31 div: "); 2306 | fflush(stdout); 2307 | 2308 | rnd_init(8); 2309 | 2310 | for (i = 1; i <= 128; i ++) { 2311 | cttk_i31_init(a, i); 2312 | cttk_i31_init(b, i); 2313 | cttk_i31_init(q, i); 2314 | cttk_i31_init(r, i); 2315 | cttk_i31_init(m, i); 2316 | cttk_i31_init(x, i); 2317 | 2318 | for (j = 0; j < 1000; j ++) { 2319 | cttk_bool bb; 2320 | 2321 | rnd(tmp1, 17); 2322 | rnd(tmp2, 17); 2323 | cttk_i31_decle_signed_trunc(a, tmp1, 17); 2324 | cttk_i31_decle_signed_trunc(b, tmp2, 17); 2325 | if (j >= 500) { 2326 | cttk_i31_rsh(b, b, i >> 1); 2327 | } 2328 | 2329 | /* 2330 | * Set bb to true if b == -1 and a == MinValue. 2331 | */ 2332 | if (i >= 2) { 2333 | cttk_i31_set_u32_trunc(x, 1); 2334 | cttk_i31_add(x, x, b); 2335 | bb = cttk_i31_eq0(x); 2336 | cttk_i31_lsh_trunc(x, a, 1); 2337 | bb = cttk_and(bb, cttk_and(cttk_i31_eq0(x), 2338 | cttk_i31_neq0(a))); 2339 | } else { 2340 | bb = cttk_bool_of_u32(i == 1 2341 | && (tmp1[0] & tmp2[0] & 1) == 1); 2342 | } 2343 | 2344 | cttk_i31_divrem(q, r, a, b); 2345 | 2346 | if (cttk_bool_to_int(cttk_i31_eq0(b))) { 2347 | check(cttk_bool_to_int(cttk_i31_isnan(q)), 2348 | "div 1 (%d,%d)", i, j); 2349 | check(cttk_bool_to_int(cttk_i31_isnan(r)), 2350 | "div 2 (%d,%d)", i, j); 2351 | } else if (cttk_bool_to_int(bb)) { 2352 | check(cttk_bool_to_int(cttk_i31_isnan(q)), 2353 | "div 3 (%d,%d)", i, j); 2354 | check(cttk_bool_to_int(cttk_i31_eq0(r)), 2355 | "div 4 (%d,%d)", i, j); 2356 | } else if (cttk_bool_to_int(cttk_i31_lt0(a))) { 2357 | check(cttk_bool_to_int(cttk_i31_leq0(r)), 2358 | "div 5 (%d,%d)", i, j); 2359 | if (cttk_bool_to_int(cttk_i31_lt0(b))) { 2360 | check(cttk_bool_to_int( 2361 | cttk_i31_lt(b, r)), 2362 | "div 6 (%d,%d)", i, j); 2363 | } else { 2364 | cttk_i31_neg(x, r); 2365 | check(cttk_bool_to_int( 2366 | cttk_i31_lt(x, b)), 2367 | "div 7 (%d,%d)", i, j); 2368 | } 2369 | cttk_i31_mul(x, b, q); 2370 | cttk_i31_add(x, x, r); 2371 | check(cttk_bool_to_int(cttk_i31_eq(x, a)), 2372 | "div 8 (%d,%d)", i, j); 2373 | } else { 2374 | check(cttk_bool_to_int(cttk_i31_geq0(r)), 2375 | "div 9 (%d,%d)", i, j); 2376 | if (cttk_bool_to_int(cttk_i31_lt0(b))) { 2377 | cttk_i31_neg(x, r); 2378 | check(cttk_bool_to_int( 2379 | cttk_i31_lt(b, x)), 2380 | "div 10 (%d,%d)", i, j); 2381 | } else { 2382 | check(cttk_bool_to_int( 2383 | cttk_i31_lt(r, b)), 2384 | "div 11 (%d,%d)", i, j); 2385 | } 2386 | cttk_i31_mul(x, b, q); 2387 | cttk_i31_add(x, x, r); 2388 | check(cttk_bool_to_int(cttk_i31_eq(x, a)), 2389 | "div 12 (%d,%d)", i, j); 2390 | } 2391 | 2392 | cttk_i31_mod(m, a, b); 2393 | 2394 | if (cttk_bool_to_int(cttk_i31_eq0(b))) { 2395 | check(cttk_bool_to_int(cttk_i31_isnan(m)), 2396 | "mod 1 (%d,%d)", i, j); 2397 | } else { 2398 | check(!cttk_bool_to_int(cttk_i31_isnan(m)), 2399 | "mod 2 (%d,%d)", i, j); 2400 | check(cttk_bool_to_int(cttk_i31_geq0(m)), 2401 | "mod 3 (%d,%d)", i, j); 2402 | if (cttk_bool_to_int(cttk_i31_geq0(r))) { 2403 | check(cttk_bool_to_int 2404 | (cttk_i31_eq(r, m)), 2405 | "mod 4 (%d,%d)", i, j); 2406 | } else if (cttk_bool_to_int(cttk_i31_gt0(b))) { 2407 | cttk_i31_sub(m, m, r); 2408 | check(cttk_bool_to_int 2409 | (cttk_i31_eq(b, m)), 2410 | "mod 5 (%d,%d)", i, j); 2411 | } else { 2412 | cttk_i31_add(m, m, b); 2413 | check(cttk_bool_to_int 2414 | (cttk_i31_eq(r, m)), 2415 | "mod 6 (%d,%d)", i, j); 2416 | } 2417 | } 2418 | } 2419 | 2420 | if ((i & 3) == 0) { 2421 | printf("."); 2422 | fflush(stdout); 2423 | } 2424 | } 2425 | 2426 | printf(" done.\n"); 2427 | fflush(stdout); 2428 | } 2429 | 2430 | static void 2431 | test_i31_bool(void) 2432 | { 2433 | cttk_i31_def(x1, 300); 2434 | cttk_i31_def(x2, 300); 2435 | cttk_i31_def(x3, 300); 2436 | zint z1, z2, z3; 2437 | int i, j; 2438 | unsigned char tmp1[100], tmp2[100], tmp3[100], tmp4[100]; 2439 | 2440 | printf("Test i31 bool: "); 2441 | fflush(stdout); 2442 | 2443 | rnd_init(9); 2444 | 2445 | for (i = 1; i <= 128; i ++) { 2446 | cttk_i31_init(x1, i); 2447 | cttk_i31_init(x2, i); 2448 | cttk_i31_init(x3, i); 2449 | 2450 | for (j = 0; j < 100; j ++) { 2451 | rnd(tmp1, 17); 2452 | rnd(tmp2, 17); 2453 | zint_decode(&z1, tmp1, 17, 0, 0); 2454 | zint_decode(&z2, tmp2, 17, 0, 0); 2455 | zint_trunc(&z1, i); 2456 | zint_trunc(&z2, i); 2457 | zint_encode(tmp1, 17, &z1, 0); 2458 | zint_encode(tmp2, 17, &z2, 0); 2459 | cttk_i31_decle_signed(x1, tmp1, 17); 2460 | cttk_i31_decle_signed(x2, tmp2, 17); 2461 | 2462 | zint_and(&z3, &z1, &z2); 2463 | zint_encode(tmp3, 17, &z3, 0); 2464 | cttk_i31_and(x3, x1, x2); 2465 | cttk_i31_encle(tmp4, 17, x3); 2466 | check(memcmp(tmp3, tmp4, 17) == 0, "and (%d,%d)", i, j); 2467 | 2468 | zint_or(&z3, &z1, &z2); 2469 | zint_encode(tmp3, 17, &z3, 0); 2470 | cttk_i31_or(x3, x1, x2); 2471 | cttk_i31_encle(tmp4, 17, x3); 2472 | check(memcmp(tmp3, tmp4, 17) == 0, "or (%d,%d)", i, j); 2473 | 2474 | zint_xor(&z3, &z1, &z2); 2475 | zint_encode(tmp3, 17, &z3, 0); 2476 | cttk_i31_xor(x3, x1, x2); 2477 | cttk_i31_encle(tmp4, 17, x3); 2478 | check(memcmp(tmp3, tmp4, 17) == 0, "xor (%d,%d)", i, j); 2479 | 2480 | zint_eqv(&z3, &z1, &z2); 2481 | zint_encode(tmp3, 17, &z3, 0); 2482 | cttk_i31_eqv(x3, x1, x2); 2483 | cttk_i31_encle(tmp4, 17, x3); 2484 | check(memcmp(tmp3, tmp4, 17) == 0, "eqv (%d,%d)", i, j); 2485 | 2486 | zint_not(&z3, &z1); 2487 | zint_encode(tmp3, 17, &z3, 0); 2488 | cttk_i31_not(x3, x1); 2489 | cttk_i31_encle(tmp4, 17, x3); 2490 | check(memcmp(tmp3, tmp4, 17) == 0, "not (%d,%d)", i, j); 2491 | } 2492 | 2493 | if ((i & 3) == 0) { 2494 | printf("."); 2495 | fflush(stdout); 2496 | } 2497 | } 2498 | 2499 | printf(" done.\n"); 2500 | fflush(stdout); 2501 | } 2502 | 2503 | int 2504 | main(void) 2505 | { 2506 | test_comparisons_32(); 2507 | test_comparisons_64(); 2508 | test_comparisons_buffers(); 2509 | test_hex(); 2510 | test_base64(); 2511 | test_mul(); 2512 | test_bitlength(); 2513 | test_i31_set(); 2514 | test_i31_codec(); 2515 | test_i31_cmp(); 2516 | test_i31_addsub(); 2517 | test_i31_mul(); 2518 | test_i31_shift(); 2519 | test_i31_div(); 2520 | test_i31_bool(); 2521 | return 0; 2522 | } 2523 | --------------------------------------------------------------------------------