├── .github └── workflows │ ├── deploy.yml │ └── main.yml ├── CMakeLists.txt ├── LICENSE ├── README.md ├── SPONSORS ├── TODO ├── changes.txt ├── demo ├── CMakeLists.txt ├── rsa.c ├── stest.c ├── test.c └── timing.c ├── doc ├── makefile └── tfm.tex ├── helper.pl ├── makefile ├── makefile.shared ├── makefile_include.mk ├── mtest ├── makefile └── mtest.c ├── random_txt_files ├── amd64.txt ├── exptmod_timings.txt ├── ltm_times.txt ├── newsqr.txt └── old_sqr_times.txt ├── sources.cmake ├── src ├── addsub │ ├── fp_add.c │ ├── fp_add_d.c │ ├── fp_addmod.c │ ├── fp_cmp.c │ ├── fp_cmp_d.c │ ├── fp_cmp_mag.c │ ├── fp_sub.c │ ├── fp_sub_d.c │ ├── fp_submod.c │ ├── s_fp_add.c │ └── s_fp_sub.c ├── bin │ ├── fp_radix_size.c │ ├── fp_read_radix.c │ ├── fp_read_signed_bin.c │ ├── fp_read_unsigned_bin.c │ ├── fp_reverse.c │ ├── fp_s_rmap.c │ ├── fp_signed_bin_size.c │ ├── fp_to_signed_bin.c │ ├── fp_to_unsigned_bin.c │ ├── fp_toradix.c │ ├── fp_toradix_n.c │ └── fp_unsigned_bin_size.c ├── bit │ ├── fp_cnt_lsb.c │ ├── fp_count_bits.c │ ├── fp_div_2.c │ ├── fp_div_2d.c │ ├── fp_lshd.c │ ├── fp_mod_2d.c │ └── fp_rshd.c ├── divide │ ├── fp_div.c │ ├── fp_div_d.c │ ├── fp_mod.c │ └── fp_mod_d.c ├── exptmod │ ├── fp_2expt.c │ └── fp_exptmod.c ├── generators │ ├── .gitignore │ ├── comba_mont_gen.c │ ├── comba_mult_gen.c │ ├── comba_mult_smallgen.c │ ├── comba_sqr_gen.c │ ├── comba_sqr_smallgen.c │ └── makefile ├── headers │ ├── tfm.h │ └── tfm_private.h ├── misc │ ├── fp_ident.c │ ├── fp_rand.c │ └── fp_set.c ├── mont │ ├── fp_mont_small.i │ ├── fp_montgomery_calc_normalization.c │ ├── fp_montgomery_reduce.c │ └── fp_montgomery_setup.c ├── mul │ ├── fp_mul.c │ ├── fp_mul_2.c │ ├── fp_mul_2d.c │ ├── fp_mul_comba.c │ ├── fp_mul_comba_12.c │ ├── fp_mul_comba_17.c │ ├── fp_mul_comba_20.c │ ├── fp_mul_comba_24.c │ ├── fp_mul_comba_28.c │ ├── fp_mul_comba_3.c │ ├── fp_mul_comba_32.c │ ├── fp_mul_comba_4.c │ ├── fp_mul_comba_48.c │ ├── fp_mul_comba_6.c │ ├── fp_mul_comba_64.c │ ├── fp_mul_comba_7.c │ ├── fp_mul_comba_8.c │ ├── fp_mul_comba_9.c │ ├── fp_mul_comba_small_set.c │ ├── fp_mul_d.c │ └── fp_mulmod.c ├── numtheory │ ├── fp_gcd.c │ ├── fp_invmod.c │ ├── fp_isprime.c │ ├── fp_isprime_ex.c │ ├── fp_lcm.c │ ├── fp_prime_miller_rabin.c │ └── fp_prime_random_ex.c └── sqr │ ├── fp_sqr.c │ ├── fp_sqr_comba.c │ ├── fp_sqr_comba_12.c │ ├── fp_sqr_comba_17.c │ ├── fp_sqr_comba_20.c │ ├── fp_sqr_comba_24.c │ ├── fp_sqr_comba_28.c │ ├── fp_sqr_comba_3.c │ ├── fp_sqr_comba_32.c │ ├── fp_sqr_comba_4.c │ ├── fp_sqr_comba_48.c │ ├── fp_sqr_comba_6.c │ ├── fp_sqr_comba_64.c │ ├── fp_sqr_comba_7.c │ ├── fp_sqr_comba_8.c │ ├── fp_sqr_comba_9.c │ ├── fp_sqr_comba_generic.c │ ├── fp_sqr_comba_small_set.c │ └── fp_sqrmod.c ├── testme.sh └── tomsfastmath.pc.in /.github/workflows/deploy.yml: -------------------------------------------------------------------------------- 1 | ############################################################################# 2 | # # 3 | # Packagecloud deployment via GH actions for TomsFastMath # 4 | # (https://github.com/libtom/tomsfastmath.git) # 5 | # # 6 | ############################################################################# 7 | 8 | name: Deploy 9 | 10 | on: 11 | workflow_dispatch 12 | 13 | jobs: 14 | deploy-to-packagecloud: 15 | runs-on: ${{ matrix.os }} 16 | strategy: 17 | matrix: 18 | os: [ ubuntu-22.04, ubuntu-24.04 ] 19 | steps: 20 | - uses: actions/checkout@v2 21 | - name: set Ubuntu codename 22 | run: | 23 | echo "ubuntu_codename="$(lsb_release -sc) >> "$GITHUB_ENV" 24 | - name: install dependencies 25 | run: | 26 | wget -O - https://apt.kitware.com/keys/kitware-archive-latest.asc 2>/dev/null | gpg --dearmor - | sudo tee /usr/share/keyrings/kitware-archive-keyring.gpg >/dev/null 27 | echo "deb [signed-by=/usr/share/keyrings/kitware-archive-keyring.gpg] https://apt.kitware.com/ubuntu/ ${{ env.ubuntu_codename }} main" | sudo tee /etc/apt/sources.list.d/kitware.list >/dev/null 28 | sudo apt-get update -qq 29 | sudo apt-get install -y cmake gcc 30 | - name: build packages 31 | run: | 32 | mkdir -p build 33 | cd build 34 | cmake -DBUILD_SHARED_LIBS=Off -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX="/usr" .. 35 | make -j$(nproc) 36 | cpack -G DEB 37 | cmake -DBUILD_SHARED_LIBS=On -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX="/usr" .. 38 | make -j$(nproc) 39 | cpack -G DEB 40 | - name: push deb packages to packagecloud.io 41 | uses: computology/packagecloud-github-action@v0.6 42 | with: 43 | PACKAGE-NAME: build/packages/ubuntu/${{ env.ubuntu_codename }}/*.deb 44 | PACKAGECLOUD-USERNAME: libtom 45 | PACKAGECLOUD-REPONAME: packages 46 | PACKAGECLOUD-DISTRO: ubuntu/${{ env.ubuntu_codename }} 47 | PACKAGECLOUD-TOKEN: ${{ secrets.PACKAGECLOUD_TOKEN }} 48 | -------------------------------------------------------------------------------- /.github/workflows/main.yml: -------------------------------------------------------------------------------- 1 | ############################################################################# 2 | # # 3 | # GitHub Actions test-suite for TomsFastMath # 4 | # (https://github.com/libtom/tomsfastmath.git) # 5 | # # 6 | ############################################################################# 7 | 8 | name: CI 9 | 10 | # Tests restricted to the following branches. 11 | on: 12 | push: 13 | branches: 14 | - master 15 | - develop 16 | - /^release\/.*$/ 17 | - /^support\/.*$/ 18 | - /^ci\/.*$/ 19 | pull_request: 20 | branches: 21 | - master 22 | - develop 23 | - /^release\/.*$/ 24 | - /^support\/.*$/ 25 | - /^ci\/.*$/ 26 | 27 | concurrency: 28 | group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} 29 | cancel-in-progress: true 30 | 31 | jobs: 32 | Testme: 33 | runs-on: ${{ matrix.os }} 34 | strategy: 35 | matrix: 36 | os: [ ubuntu-22.04 ] 37 | # The environment given to the programs in the build 38 | # We have only one program and the variable $BUILDOPTIONS 39 | # has only the options to that program: testme.sh 40 | 41 | config: 42 | # GCC for the x86-64 architecture (64-bit longs and 64-bit pointers) 43 | - { CC: 'gcc', DEPS: 'gcc' } 44 | - { CC: 'gcc-9', DEPS: 'gcc-9' } 45 | - { CC: 'gcc-10', DEPS: 'gcc-10' } 46 | - { CC: 'gcc-11', DEPS: 'gcc-11' } 47 | - { CC: 'gcc-12', DEPS: 'gcc-12' } 48 | 49 | # clang for x86-64 architecture (64-bit longs and 64-bit pointers) 50 | - { CC: 'clang', DEPS: 'clang' } 51 | - { CC: 'clang-11', DEPS: 'clang-11 llvm-11' } 52 | - { CC: 'clang-12', DEPS: 'clang-12 llvm-12' } 53 | - { CC: 'clang-13', DEPS: 'clang-13 llvm-13' } 54 | - { CC: 'clang-14', DEPS: 'clang-14 llvm-14' } 55 | - { CC: 'clang-15', DEPS: 'clang-15 llvm-15' } 56 | 57 | makefile: [ makefile, makefile.shared ] 58 | steps: 59 | - uses: actions/checkout@v4 60 | - name: install dependencies 61 | run: | 62 | sudo apt-get update -qq 63 | sudo apt-get install libtool-bin -y ${{ matrix.config.DEPS }} 64 | sudo apt-cache search gcc | grep '^gcc-[0-9\.]* ' 65 | sudo apt-cache search clang | grep compiler 66 | - name: run tests 67 | env: 68 | CC: ${{ matrix.config.CC }} 69 | run: | 70 | $CC -dumpversion 71 | make -f ${{ matrix.makefile }} test_standalone >gcc_errors_1.log 2>gcc_errors_2.log 72 | ./test >test_std.log 2>test_err.log 73 | # In case of a CI error a success might get signaled 74 | # even without any test run. This file also keeps any notes 75 | # printed from the tests which might come handy from time 76 | # to time. 77 | - name: regular logs 78 | if: ${{ !failure() }} 79 | run: | 80 | cat test_*.log || true 81 | # Compilation failures are in gcc_errors_*.log 82 | # Failed tests in test_*.log 83 | # Files do not exist in case of success 84 | - name: error logs 85 | if: ${{ failure() }} 86 | run: | 87 | cat test_*.log || true 88 | cat gcc_errors_*.log || true 89 | 90 | amalgam: 91 | runs-on: ubuntu-22.04 92 | steps: 93 | - uses: actions/checkout@v4 94 | - name: build stest with amalgamated sources 95 | run: | 96 | make amalgamated_stest 97 | 98 | CMake: 99 | runs-on: ${{ matrix.os }} 100 | strategy: 101 | matrix: 102 | os: [ ubuntu-22.04, ubuntu-24.04 ] 103 | build_type: [ '', -DCMAKE_BUILD_TYPE=Debug, -DCMAKE_BUILD_TYPE=Release, -DCMAKE_BUILD_TYPE=RelWithDebInfo, -DCMAKE_BUILD_TYPE=MinSizeRel ] 104 | cc: [ clang, gcc ] 105 | config: 106 | # Static library build 107 | - { CMAKEOPTIONS: '-DBUILD_SHARED_LIBS=Off' } 108 | # Shared library build 109 | - { CMAKEOPTIONS: '-DBUILD_SHARED_LIBS=On' } 110 | steps: 111 | - uses: actions/checkout@v4 112 | - name: install dependencies 113 | run: | 114 | sudo apt-get update -qq 115 | sudo apt-get install -y cmake gcc clang llvm 116 | - name: build 117 | run: | 118 | mkdir build 119 | cd build 120 | CC=${{ matrix.cc }} cmake ${{ matrix.config.CMAKEOPTIONS }} ${{ matrix.build_type }} .. 121 | make -j$(nproc) 122 | - name: test 123 | run: | 124 | cd build 125 | CC=${{ matrix.cc }} cmake ${{ matrix.config.CMAKEOPTIONS }} ${{ matrix.build_type }} -DBUILD_TESTING=On .. 126 | make -j$(nproc) 127 | ctest 128 | - name: test (in demo folder) 129 | run: | 130 | mkdir -p demo/build 131 | cd demo/build 132 | CC=${{ matrix.cc }} cmake ${{ matrix.config.CMAKEOPTIONS }} ${{ matrix.build_type }} .. 133 | make -j$(nproc) 134 | ctest 135 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The LibTom license 2 | 3 | This is free and unencumbered software released into the public domain. 4 | 5 | Anyone is free to copy, modify, publish, use, compile, sell, or 6 | distribute this software, either in source code form or as a compiled 7 | binary, for any purpose, commercial or non-commercial, and by any 8 | means. 9 | 10 | In jurisdictions that recognize copyright laws, the author or authors 11 | of this software dedicate any and all copyright interest in the 12 | software to the public domain. We make this dedication for the benefit 13 | of the public at large and to the detriment of our heirs and 14 | successors. We intend this dedication to be an overt act of 15 | relinquishment in perpetuity of all present and future rights to this 16 | software under copyright law. 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 NONINFRINGEMENT. 21 | IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 22 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 23 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 24 | OTHER DEALINGS IN THE SOFTWARE. 25 | 26 | For more information, please refer to 27 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | tomsfastmath 2 | ============ 3 | 4 | See doc/tfm.pdf for a detailed documentation (https://github.com/libtom/tomsfastmath/releases/latest has a pdf for the most recent release). 5 | 6 | 7 | Project Status 8 | ============== 9 | 10 | master: [![Build Status](https://github.com/libtom/tomsfastmath/actions/workflows/main.yml/badge.svg?branch=master)](https://github.com/libtom/tomsfastmath/actions/workflows/main.yml) 11 | 12 | develop: [![Build Status](https://github.com/libtom/tomsfastmath/actions/workflows/main.yml/badge.svg?branch=develop)](https://github.com/libtom/tomsfastmath/actions/workflows/main.yml) 13 | -------------------------------------------------------------------------------- /SPONSORS: -------------------------------------------------------------------------------- 1 | Development of TomsFastMath was sponsored by three groups. Two companies that use LTC and LTM commercially 2 | and one individual who decided he wanted to help out by being generous. 3 | 4 | Thanks goes to them [though they wished to remain anonymous] and people like them. 5 | 6 | -------------------------------------------------------------------------------- /TODO: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/libtom/tomsfastmath/b2b4d030cf12431946b3fc485847b2ca026278c1/TODO -------------------------------------------------------------------------------- /changes.txt: -------------------------------------------------------------------------------- 1 | April 4th, 2017 2 | v0.13.1 3 | -- Fix missing fp_rand symbol in shared library 4 | -- Fix some parameters in API signatures that should've been const 5 | -- Bugfixes and improvements contributed by Sebastian Siewior, Reiner Herrmann and Mathias Tausig 6 | 7 | October 24th, 2015 8 | v0.13.0 9 | -- Add fp_rand() 10 | -- Fix bug in fp_sub() reported by Martins Mozeiko 11 | -- Fix bugs/apply patches in fp_mul() and fp_sqr() reported by rasky 12 | -- Fix bugs in fp_read_radix() 13 | -- Fix build issues for Linux x32 ABI 14 | -- Sebastian Siewior provided fp_toradix_n(), 15 | reported multiple issues on behalf of ClamAV 16 | and did most of the testing work to be able to push this release out. 17 | -- Fix a load of compiler warnings. 18 | 19 | March 14th, 2007 20 | 0.12 -- Christophe Devine contributed MIPS asm w00t 21 | ++ quick release to get the MIPS code out there 22 | 23 | March 10th, 2007 24 | 0.11 -- re-org'ed the source tree, it's cooler now 25 | -- cleaned up mul/sqr so there is only one file per unit, should help building with older compilers and/or on slower boxes 26 | -- [CRI] optimized fp_read_unsigned_bin 27 | -- fixed -0 ... again ... I now have less hair on my head. 28 | -- [CRI] renamed bn_reverse() -> fp_reverse() 29 | 30 | November 1st, 2006 31 | 0.10 -- Unrolled Montgomery for 1..16 digits with TFM_SMALL_MONT_SET between 10% and 25% speedup depending on size. 32 | -- fixed fp_sqr_comba.c so it builds in ISO C mode [Andreas Lange] 33 | -- cisc@broadpark.no pointed out fp_radix_size() had a few typos that affected correctness. Fixed. 34 | -- Added support for ECC performance, e.g. define "-DTFM_ALREADY_SET -DTFM_ECC192" and it will disable 35 | all of the unrolled code EXCEPT what is required for ECC P-192. It autodetects 32/64-bit platforms too. It's super neato. 36 | Support for 192, 224, 256, 384 and 521 bit curves through the defines [see tfm.h] 37 | -- AVR32 support added, define TFM_AVR32 to enable 38 | 39 | April 4th, 2006 40 | 0.09 -- Bruce Guenter suggested I use --tag=CC for libtool builds where the compiler may think it's C++. 41 | -- Added support for k=1 in exptmod for RSA exponents. Makes it more competitive with other libraries 42 | -- added cutoffs to the comba32 sqr/mul code to better handle 640, 786 and 896 bit operands (e.g. for RSA-1280, RSA-1536 and RSA-1792), really no effect 43 | for 64-bit boxes as these represent 1280, 1536 and 1792 bit operands (not likely to be invoked). 44 | -- Removed karatsuba from the mul/sqr since they're not useful and slow. 45 | -- added 20, 24 and 28 digit multipliers for oddsized RSA support. You can easily disable them by uncommenting the TFM_SQRXX and TFM_MULXX lines in 46 | tfm.h to save space. Now GMP and TFM are roughly the same speed on the Pentium-M for RSA with LTC. 47 | -- unrolled SSE2 code and optimize for platforms with load/store pipes (e.g. can store and load in a cycle). Got 4% or so boost on my Dothan laptop (marginal improvement on a P4 Prescott) 48 | 49 | Jan 26th, 2006 50 | 0.08 -- Fixed a bug in the generic mult/sqr where we overflowed by one digit 51 | 52 | November 18th, 2005 53 | 0.07 -- Fixes to fp_mul and fp_sqr to clean up the handling of the defines, fix to tfm.h to also clear up the prototypes. 54 | -- Updates to build and run on a IBM PPC 405 [using GCC 3.4.4] 55 | -- Made the "make" command renamable in the build system 56 | 57 | October 31st, 2005 58 | 0.06 -- fixed fp_mul() and fp_sqr() to trim digits when overflows would occur. Produces numerically inprecise results 59 | (e.g. the lower FP_SIZE digits) but shouldn't segfault at least ;-) 60 | -- Updated the combas so you can turn on and off specific unrolled loops at build time 61 | -- Michael Heyman reported a bug in s_fp_sub() that was pretty substantial and a bug in fp_montgomery_calc_normalization(). Fixed. 62 | 63 | August 1st, 2005 64 | 0.05 -- Quick fix to the fp_invmod.c code to let it handle even moduli [required for LTC] 65 | -- Added makefile.shared to make shared objects [required for LTC] 66 | -- Improved makefiles to make them way more configurable 67 | -- Added timing resistant fp_exptmod() enabled with TFM_TIMING_RESISTANT 68 | 69 | July 23rd, 2005 70 | 0.04 -- Fixed bugs in the SSE2 squaring code 71 | -- Rewrote the multipliers to be optimized for small inputs 72 | -- Nelson Bolyard of the NSS crew submitted [among other things] new faster Montgomery reduction 73 | code. It brings the performance for small numbers on the AMD64 and all numbers on the P4 74 | to a new level. Thanks! 75 | -- Added missing ARM support for fp_montgomery_reduce.c that the NSS folk left off, Officially 76 | the ARM code is for v4 and above WITH the "M" multiplier support (e.g. umlal instruction) 77 | -- Added PPC32 support, define TFM_PPC32 to enable it, I used the "PowerPC 6xx" instruction 78 | databook for reference. Does not require altivec. Should be fairly portable to the other 79 | 32-bit PPCs provided they have mullw and mulhwu instructions. 80 | [Note: porting the macros to PPC64 should be trivial, anyone with a shell to lend... email me!] 81 | -- Rewrote the config a bit in tfm.h so you can better choose which set of "oh my god that's huge" code to 82 | enable for your task. "generic" functions are ALWAYS included which are smaller but will cover the 83 | gaps in the coverage for ya. 84 | -- The PPC32 code has been verified to function on a Darwin box running GCC 2.95.2 85 | [Thanks to the folk at PeerSec for lending me a shell to use] 86 | -- Fixed a bug in fp_exptmod() where if the exponent was negative AND the destination the output 87 | would have the sign set to FP_NEG. 88 | 89 | March 1st, 2005 90 | 0.03 -- Optimized squaring 91 | -- Applied new license header to all files (still PD) 92 | 93 | September 18th, 2004 94 | 0.02 -- Added TFM_LARGE to turn on/off 16x combas to save even more space. 95 | This also helps prevent killing the cache on smaller cpus. 96 | -- Cast memset to void in fp_init() to catch people who misuse the function (e.g. expect return) 97 | Thanks to Johan Lindh 98 | -- Cleaned up x86-64 support [faster montgomery reductions] 99 | -- Autodetects x86-32 and x86-64 and enables it's asm now 100 | -- Made test demo build cleaner in multilib platforms [e.g. mixed 32/64 bits] 101 | -- Fix to fp_mod to ensure that remainder is of the same sign as the modulus. 102 | -- Fixed bug in fp_montgomery_calc_normalization for single digit moduli 103 | -- cleaned up ISO C macros in comba/mont to avoid branches [works best with GCC 3.4.x branch] 104 | -- Added more testing to tfm.h to help detect misconfigured builds 105 | -- Added TFM_NO_ASM which forces ASM off [even if it was autodetected]. 106 | -- Added fp_radix_size() to API 107 | -- Cleaned up demo/test.c to build with far fewer warnings (mostly %d => %lu fixes) 108 | -- fp_exptmod() now supports negative exponent and base>modulus cases 109 | -- Added fp_ident() which gives a string showing how TFM was configured. Useful for debuging... 110 | -- fix gen.pl script so it includes the whole source tree now 111 | 112 | August 25th, 2004 113 | 0.01 -- Initial Release 114 | -------------------------------------------------------------------------------- /demo/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Unlicense 2 | # 3 | # LibTomMath, a free open source portable number theoretic multiple-precision 4 | # integer (MPI) library written entirely in C. 5 | # 6 | 7 | cmake_minimum_required(VERSION 3.10) 8 | 9 | set(TFM_TEST test-tfm) 10 | 11 | # This file can be included from the top level or used stand-alone 12 | if(PROJECT_NAME) 13 | set(LIBRARY_NAME ${PROJECT_NAME}) 14 | else() 15 | # Define an independent project and all the necessary stuff around 16 | project(${TFM_TEST} 17 | LANGUAGES C) 18 | set(LIBRARY_NAME tomsfastmath) 19 | find_package(${LIBRARY_NAME}) 20 | include(CTest) 21 | if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) 22 | set(CMAKE_BUILD_TYPE "Release") 23 | endif() 24 | endif() 25 | 26 | #----------------------------------------------------------------------------- 27 | # Compose CFLAGS etc. 28 | #----------------------------------------------------------------------------- 29 | 30 | set(CMAKE_C_FLAGS "-DTFM_DEMO_TEST_VS_MTEST=0") 31 | set(CMAKE_C_FLAGS_DEBUG "-g3 -O1") 32 | 33 | #----------------------------------------------------------------------------- 34 | # demo target 35 | #----------------------------------------------------------------------------- 36 | 37 | add_executable(${TFM_TEST} 38 | ${CMAKE_CURRENT_SOURCE_DIR}/test.c 39 | ) 40 | 41 | target_include_directories(${TFM_TEST} PRIVATE 42 | ${CMAKE_CURRENT_SOURCE_DIR} 43 | $<$:${CMAKE_CURRENT_SOURCE_DIR}/..> 44 | ) 45 | 46 | target_link_libraries(${TFM_TEST} PRIVATE 47 | ${LIBRARY_NAME} 48 | ) 49 | 50 | target_compile_options(${TFM_TEST} PRIVATE 51 | ${TFM_C_FLAGS} 52 | ) 53 | target_link_options(${TFM_TEST} BEFORE PUBLIC 54 | ${TFM_LD_FLAGS} 55 | ) 56 | 57 | #----------------------------------------------------------------------------- 58 | # CTest 59 | #----------------------------------------------------------------------------- 60 | add_test(NAME ${TFM_TEST} COMMAND ${TFM_TEST}) 61 | 62 | find_program(MEMORYCHECK_COMMAND valgrind) 63 | set(MEMORYCHECK_COMMAND_OPTIONS "--trace-children=yes --leak-check=full") 64 | -------------------------------------------------------------------------------- /demo/rsa.c: -------------------------------------------------------------------------------- 1 | /* TomsFastMath, a fast ISO C bignum library. -- Tom St Denis */ 2 | /* SPDX-License-Identifier: Unlicense */ 3 | 4 | #include "tfm.h" 5 | #include 6 | 7 | int main(void) 8 | { 9 | fp_int d, e, n, c, m, e_m; 10 | clock_t t1; 11 | int x; 12 | 13 | /* read in the parameters */ 14 | fp_read_radix(&n, "ce032e860a9809a5ec31e4b0fd4b546f8c40043e3d2ec3d8f49d8f2f3dd19e887094ee1af75caa1c2e6cd9ec78bf1dfd6280002ac8c30ecd72da2e4c59a28a9248048aaae2a8fa627f71bece979cebf9f8eee2bd594d4a4f2e791647573c7ec1fcbd320d3825be3fa8a17c97086fdae56f7086ce512b81cc2fe44161270ec5e9", 16); 15 | fp_read_radix(&e, "10001", 16); 16 | fp_read_radix(&m, "39f5a911250f45b99390e2df322b33c729099ab52b5879d06b00818cce57c649a66ed7eb6d8ae214d11caf9c81e83a7368cf0edb2b71dad791f13fecf546123b40377851e67835ade1d6be57f4de18a62db4cdb1880f4ab2e6a29acfd85ca22a13dc1f6fee2621ef0fc8689cd738e6f065c033ec7c148d8d348688af83d6f6bd", 16); 17 | fp_read_radix(&c, "9ff70ea6968a04530e6b06bf01aa937209cc8450e76ac19477743de996ba3fb445923c947f8d0add8c57efa51d15485309918459da6c1e5a97f215193b797dce98db51bdb4639c2ecfa90ebb051e3a2daeffd27a7d6e62043703a7b15e0ada5170427b63099cd01ef52cd92d8723e5774bea32716aaa7f5adbae817fb12a5b50", 16); 18 | 19 | /* test it */ 20 | fp_exptmod(&m, &e, &n, &e_m); 21 | if (fp_cmp(&e_m, &c)) { 22 | char buf[1024]; 23 | printf("Encrypted text not equal\n"); 24 | fp_toradix(&e_m, buf, 16); 25 | printf("e_m == %s\n", buf); 26 | return 0; 27 | } 28 | 29 | printf("CLOCKS_PER_SEC = %llu\n", (unsigned long long)CLOCKS_PER_SEC); 30 | t1 = clock(); 31 | for (x = 0; x < 1000; x++) { 32 | fp_exptmod(&m, &e, &n, &e_m); 33 | } 34 | t1 = clock() - t1; 35 | printf("1000 RSA operations took %10.5g seconds\n", (double)t1 / (double)CLOCKS_PER_SEC); 36 | printf("RSA encrypt/sec %10.5g\n", (double)CLOCKS_PER_SEC / ((double)t1 / 1000.0) ); 37 | 38 | /* read in the parameters */ 39 | fp_read_radix(&n, "a7f30e2e04d31acc6936916af1e404a4007adfb9e97864de28d1c7ba3034633bee2cd9d5da3ea3cdcdc9a6f3daf5702ef750f4c3aadb0e27410ac04532176795995148cdb4691bd09a8a846e3e24e073ce2f89b34dfeb2ee89b646923ca60ee3f73c4d5397478380425e7260f75dfdc54826e160395b0889b1162cf115a9773f", 16); 40 | fp_read_radix(&d, "16d166f3c9a404d810d3611e6e8ed43293fe1db75c8906eb4810785a4b82529929dade1db7f11ac0335d5a59773e3167b022479eedefa514a0399db5c900750a56323cf9f5b0f21e7d60a46d75f3fcaabf30a63cbe34048b741a57ac36a13914afda798709dea5771f8d456cf72ec5f3afc1d88d023de40311143a36e7028739", 16); 41 | fp_read_radix(&c, "7d216641c32543f5b8428bdd0b11d819cfbdb16f1df285247f677aa4d44de62ab064f4a0d060ec99cb94aa398113a4317f2c550d0371140b0fd2c88886cac771812e72faad4b7adf495b9b850b142ccd7f45c0a27f164c8c7731731c0015f69d0241812e769d961054618aeb9e8e8989dba95714a2cf56c9e525c5e34b5812dd", 16); 42 | fp_read_radix(&m, "5f323bf0b394b98ffd78727dc9883bb4f42287def6b60fa2a964b2510bc55d61357bf5a6883d2982b268810f8fef116d3ae68ebb41fd10d65a0af4bec0530eb369f37c14b55c3be60223b582372fb6589b648d5a0c7252d1ae2dae5809785d993e9e5d0c4d9b0bcba0cde0d6671734747fba5483c735e1dab7df7b10ec6f62d8", 16); 43 | 44 | /* test it */ 45 | fp_exptmod(&c, &d, &n, &e_m); 46 | if (fp_cmp(&e_m, &m)) { 47 | char buf[1024]; 48 | printf("Decrypted text not equal\n"); 49 | fp_toradix(&e_m, buf, 16); 50 | printf("e_m == %s\n", buf); 51 | return 0; 52 | } 53 | 54 | t1 = clock(); 55 | for (x = 0; x < 100; x++) { 56 | fp_exptmod(&c, &d, &n, &e_m); 57 | } 58 | t1 = clock() - t1; 59 | printf("100 RSA operations took %10.5g seconds\n", (double)t1 / (double)CLOCKS_PER_SEC); 60 | printf("RSA decrypt/sec %10.5g\n", (double)CLOCKS_PER_SEC / ((double)t1 / 100.0) ); 61 | 62 | 63 | /* test half size */ 64 | fp_rshd(&n, n.used >> 1); 65 | fp_rshd(&d, d.used >> 1); 66 | fp_rshd(&c, c.used >> 1); 67 | printf("n.used == %4d bits\n", n.used * DIGIT_BIT); 68 | 69 | /* ensure n is odd */ 70 | n.dp[0] |= 1; 71 | t1 = clock(); 72 | for (x = 0; x < 100; x++) { 73 | fp_exptmod(&c, &d, &n, &e_m); 74 | } 75 | t1 = clock() - t1; 76 | printf("100 RSA-half operations took %10.5g seconds\n", (double)t1 / (double)CLOCKS_PER_SEC); 77 | printf("RSA decrypt/sec %10.5g (estimate of RSA-1024-CRT) \n", (double)CLOCKS_PER_SEC / ((double)t1 / 50.0) ); 78 | 79 | 80 | 81 | return 0; 82 | } 83 | -------------------------------------------------------------------------------- /demo/stest.c: -------------------------------------------------------------------------------- 1 | /* TomsFastMath, a fast ISO C bignum library. -- Tom St Denis */ 2 | /* SPDX-License-Identifier: Unlicense */ 3 | 4 | /* A simple static test program. */ 5 | #include 6 | 7 | #ifdef GBA_MODE 8 | #include 9 | #define DISPLAY(x) modetxt_puts(vfb, x, 1) 10 | #endif 11 | 12 | #ifndef DISPLAY 13 | #define DISPLAY(x) printf(x) 14 | #define DISPLAY_P(...) printf(__VA_ARGS__) 15 | #else 16 | #define DISPLAY_P(...) (void)0 17 | #define fp_dump(n,p) do{}while(0) 18 | #endif 19 | 20 | #ifndef fp_dump 21 | void fp_dump(const char* n, fp_int* p) 22 | { 23 | int sz; 24 | if (fp_radix_size(p, 2, &sz) != FP_OKAY) 25 | return; 26 | char* str = malloc(sz); 27 | if (!str) 28 | return; 29 | #ifdef STEST_VERBOSE 30 | fp_toradix(p, str, 2); 31 | DISPLAY_P("%s = 0b%s\n", n, str); 32 | fp_toradix(p, str, 16); 33 | DISPLAY_P("%s = 0x%s\n", n, str); 34 | #endif 35 | fp_toradix(p, str, 10); 36 | DISPLAY_P("%s = %s\n", n, str); 37 | free(str); 38 | } 39 | #endif 40 | 41 | #ifdef GBA_MODE 42 | int c_main(void) 43 | #else 44 | int main(void) 45 | #endif 46 | { 47 | fp_int a,b,c,d,e,f; 48 | fp_digit dp; 49 | 50 | fp_init(&a); 51 | fp_init(&b); 52 | fp_init(&c); 53 | fp_init(&d); 54 | fp_init(&e); 55 | fp_init(&f); 56 | 57 | #ifdef GBA_MODE 58 | install_common(); 59 | modetxt_init(); 60 | modetxt_gotoxy(0,0); 61 | #endif 62 | 63 | DISPLAY_P("TFM Ident string:\n%s\n\n", fp_ident()); 64 | 65 | /* test multiplication */ 66 | fp_read_radix(&a, "3453534534535345345341230891273", 10); 67 | fp_read_radix(&b, "2394873294871238934718923" , 10); 68 | fp_read_radix(&c, "8270777629674273015508507050766235312931312159028658979", 10); 69 | fp_mul(&a, &b, &d); 70 | if (fp_cmp(&c, &d)) { 71 | DISPLAY("mul failed\n"); 72 | return -1; 73 | } else { 74 | DISPLAY("mul passed\n"); 75 | } 76 | 77 | /* test multiplication */ 78 | fp_read_radix(&a, "30481290320498235987349712308523652378643912563478232907782361237864278207235782364578264891274789264278634289739", 10); 79 | fp_read_radix(&b, "48761478126387263782638276327836287632836278362837627838736278362923698724823749238732" , 10); 80 | fp_read_radix(&c, "1486312771227034563307950634490737985563993459700941115664257275795366623795590136120579100118233580357115074068815507257715906295105536107921754177810976863679300283932188006885811950341132768970948", 10); 81 | fp_mul(&a, &b, &d); 82 | if (fp_cmp(&c, &d)) { 83 | DISPLAY("mul failed\n"); 84 | return -1; 85 | } else { 86 | DISPLAY("mul passed\n"); 87 | } 88 | 89 | /* test multiplication */ 90 | fp_read_radix(&a, "115792089237316195423570985008687907853269984665640564039457584007913129639935", 10); 91 | fp_read_radix(&b, "174224571863520493293247799005065324265471" , 10); 92 | fp_read_radix(&c, "20173827172553973356686868531273530268200710714389071377794102651988800859098544338487575161443744102709980552583184385", 10); 93 | fp_mul(&a, &b, &d); 94 | if (fp_cmp(&c, &d)) { 95 | DISPLAY("mul failed\n"); 96 | return -1; 97 | } else { 98 | DISPLAY("mul passed\n"); 99 | } 100 | 101 | /* test squaring */ 102 | fp_read_radix(&a, "298723982748923478923473927489237289347238947238947238947238972893", 10); 103 | fp_read_radix(&b, "89236017869379132235512787068367546521309689412262624434964313994127411682542855190667724226920696163962644836740110835385588789449" , 10); 104 | fp_sqr(&a, &c); 105 | if (fp_cmp(&c, &b)) { 106 | DISPLAY("sqr failed\n"); 107 | return -1; 108 | } else { 109 | DISPLAY("sqr passed\n"); 110 | } 111 | 112 | fp_read_radix(&a, "397823894238973128942895123894327123941724927848927349274897238978927593487012378490184789429812734982738972389", 10); 113 | fp_read_radix(&b, "158263850827461677491961439999264901067636282938352531932899298293270945997930087353471903166601507321298827087008336951419604640736464667188494668962822678461626245753696845719301945679092882499787869509090904187704367321" , 10); 114 | fp_sqr(&a, &c); 115 | if (fp_cmp(&c, &b)) { 116 | DISPLAY("sqr failed\n"); 117 | return -1; 118 | } else { 119 | DISPLAY("sqr passed\n"); 120 | } 121 | 122 | fp_read_radix(&a, "13407807929942597099574024998205846127479365820592393377723561443721764030073546976801874298166903427690031858186486050853753882811946569946433649006084095", 10); 123 | fp_read_radix(&b, "179769313486231590772930519078902473361797697894230657273430081157732675805500963132708477322407536021120113879871393357658789768814416622492847430639474097562152033539671286128252223189553839160721441767298250321715263238814402734379959506792230903356495130620869925267845538430714092411695463462326211969025" , 10); 124 | fp_sqr(&a, &c); 125 | if (fp_cmp(&c, &b)) { 126 | DISPLAY("sqr failed\n"); 127 | return -1; 128 | } else { 129 | DISPLAY("sqr passed\n"); 130 | } 131 | 132 | 133 | /* montgomery reductions */ 134 | fp_read_radix(&a, "234892374892374893489123428937892781237863278637826327367637836278362783627836783678363", 10); 135 | fp_read_radix(&b, "4447823492749823749234123489273987393983289319382762756425425425642727352327452374521", 10); 136 | #ifdef FP_64BIT 137 | fp_read_radix(&c, "942974496560863503657226741422301598807235487941674147660989764036913926327577165648", 10); 138 | #else 139 | fp_read_radix(&c, "2396271882990732698083317035605836523697277786556053771759862552557086442129695099100", 10); 140 | #endif 141 | if (fp_montgomery_setup(&b, &dp) != FP_OKAY) 142 | DISPLAY("mont setup failed\n"); 143 | fp_montgomery_reduce(&a, &b, dp); 144 | if (fp_cmp(&a, &c)) { 145 | DISPLAY("mont failed\n"); 146 | fp_dump("a (is )", &a); 147 | fp_dump("c (should)", &c); 148 | return -1; 149 | } else { 150 | DISPLAY("mont passed\n"); 151 | } 152 | 153 | fp_read_radix(&a, "2348923748923748934891234456645654645645684576353428937892781237863278637826327367637836278362783627836783678363", 10); 154 | fp_read_radix(&b, "444782349274982374923412348927398739398328931938276275642542542564272735232745237452123424324324444121111119", 10); 155 | fp_read_radix(&c, "45642613844554582908652603086180267403823312390990082328515008314514368668691233331246183943400359349283420", 10); 156 | if (fp_montgomery_setup(&b, &dp) != FP_OKAY) 157 | DISPLAY("mont setup failed\n"); 158 | fp_montgomery_reduce(&a, &b, dp); 159 | if (fp_cmp(&a, &c)) { 160 | DISPLAY("mont failed\n"); 161 | fp_dump("a (is )", &a); 162 | fp_dump("c (should)", &c); 163 | return -1; 164 | } else { 165 | DISPLAY("mont passed\n"); 166 | } 167 | 168 | fp_read_radix(&a, "234823424242342923748923748934891234456645654645645684576353424972378234762378623891236834132352375235378462378489378927812378632786378263273676378362783627555555555539568389052478124618461834763837685723645827529034853490580134568947341278498542893481762349723907847892983627836783678363", 10); 169 | fp_read_radix(&b, "44478234927456563455982374923412348927398739398328931938276275642485623481638279025465891276312903262837562349056234783648712314678120389173890128905425242424239784256427", 10); 170 | fp_read_radix(&c, "33160865265453361650564031464519042126185632333462754084489985719613480783282357410514898819797738034600484519472656152351777186694609218202276509271061460265488348645081", 10); 171 | if (fp_montgomery_setup(&b, &dp) != FP_OKAY) 172 | DISPLAY("mont setup failed\n"); 173 | fp_montgomery_reduce(&a, &b, dp); 174 | if (fp_cmp(&a, &c)) { 175 | DISPLAY("mont failed\n"); 176 | fp_dump("a (is )", &a); 177 | fp_dump("c (should)", &c); 178 | return -1; 179 | } else { 180 | DISPLAY("mont passed\n"); 181 | } 182 | 183 | 184 | return 0; 185 | } 186 | -------------------------------------------------------------------------------- /doc/makefile: -------------------------------------------------------------------------------- 1 | # TomsFastMath, a fast ISO C bignum library. -- Tom St Denis 2 | # SPDX-License-Identifier: Unlicense 3 | 4 | ifeq ($V,1) 5 | silent= 6 | silent_stdout= 7 | else 8 | silent=@ 9 | silent_stdout= > /dev/null 10 | endif 11 | 12 | all: tfm.pdf 13 | 14 | docdvi: tfm.tex 15 | cp tfm.tex tfm.bak 16 | touch -r tfm.tex tfm.bak 17 | (printf "%s" "\def\fixedpdfdate{"; date +'D:%Y%m%d%H%M%S%:z' -d @$$(stat --format=%Y tfm.tex) | sed "s/:\([0-9][0-9]\)$$/'\1'}/g") > tfm-deterministic.tex 18 | printf "%s\n" "\pdfinfo{" >> tfm-deterministic.tex 19 | printf "%s\n" " /CreationDate (\fixedpdfdate)" >> tfm-deterministic.tex 20 | printf "%s\n}\n" " /ModDate (\fixedpdfdate)" >> tfm-deterministic.tex 21 | cat tfm.tex >> tfm-deterministic.tex 22 | mv tfm-deterministic.tex tfm.tex 23 | touch -r tfm.bak tfm.tex 24 | touch tfm.ind 25 | latex tfm $(silent_stdout) 26 | latex tfm $(silent_stdout) 27 | makeindex tfm 28 | latex tfm $(silent_stdout) 29 | 30 | tfm.pdf: docdvi 31 | latex tfm $(silent_stdout) 32 | pdflatex tfm $(silent_stdout) 33 | sed -b -i 's,^/ID \[.*\]$$,/ID [<0> <0>],g' tfm.pdf 34 | mv tfm.bak tfm.tex 35 | 36 | docs: tfm.pdf 37 | -------------------------------------------------------------------------------- /helper.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env perl 2 | 3 | use strict; 4 | use warnings; 5 | 6 | use Getopt::Long; 7 | use File::Find 'find'; 8 | use File::Basename 'basename'; 9 | use File::Glob 'bsd_glob'; 10 | 11 | sub read_file { 12 | my $f = shift; 13 | open my $fh, "<", $f or die "FATAL: read_rawfile() cannot open file '$f': $!"; 14 | binmode $fh; 15 | return do { local $/; <$fh> }; 16 | } 17 | 18 | sub write_file { 19 | my ($f, $data) = @_; 20 | die "FATAL: write_file() no data" unless defined $data; 21 | open my $fh, ">", $f or die "FATAL: write_file() cannot open file '$f': $!"; 22 | binmode $fh; 23 | print $fh $data or die "FATAL: write_file() cannot write to '$f': $!"; 24 | close $fh or die "FATAL: write_file() cannot close '$f': $!"; 25 | return; 26 | } 27 | 28 | sub check_source { 29 | my @all_files = (bsd_glob("makefile*"), bsd_glob("*.sh"), bsd_glob("*.pl")); 30 | find({ wanted=>sub { push @all_files, $_ if -f $_ }, no_chdir=>1 }, qw/src demo/); 31 | 32 | my $fails = 0; 33 | for my $file (sort @all_files) { 34 | next unless $file =~ /\.(c|h|pl|py|sh)$/ || basename($file) =~ /^makefile/i; 35 | my $troubles = {}; 36 | my $lineno = 1; 37 | my $content = read_file($file); 38 | push @{$troubles->{crlf_line_end}}, '?' if $content =~ /\r/; 39 | for my $l (split /\n/, $content) { 40 | push @{$troubles->{merge_conflict}}, $lineno if $l =~ /^(<<<<<<<|=======|>>>>>>>)([^<=>]|$)/; 41 | push @{$troubles->{trailing_space}}, $lineno if $l =~ / $/; 42 | push @{$troubles->{tab}}, $lineno if $l =~ /\t/ && basename($file) !~ /^makefile/i; 43 | push @{$troubles->{non_ascii_char}}, $lineno if $l =~ /[^[:ascii:]]/; 44 | push @{$troubles->{cpp_comment}}, $lineno if $file =~ /\.(c|h)$/ && ($l =~ /\s\/\// || $l =~ /\/\/\s/); 45 | # in ./src we prefer using XMEMCPY, XMALLOC, XFREE ... 46 | push @{$troubles->{unwanted_memcpy}}, $lineno if $file =~ /^src\/.*\.c$/ && $l =~ /\bmemcpy\s*\(/; 47 | push @{$troubles->{unwanted_malloc}}, $lineno if $file =~ /^src\/.*\.c$/ && $l =~ /\bmalloc\s*\(/; 48 | push @{$troubles->{unwanted_realloc}}, $lineno if $file =~ /^src\/.*\.c$/ && $l =~ /\brealloc\s*\(/; 49 | push @{$troubles->{unwanted_calloc}}, $lineno if $file =~ /^src\/.*\.c$/ && $l =~ /\bcalloc\s*\(/; 50 | push @{$troubles->{unwanted_free}}, $lineno if $file =~ /^src\/.*\.c$/ && $l =~ /\bfree\s*\(/; 51 | push @{$troubles->{unwanted_memset}}, $lineno if $file =~ /^src\/.*\.c$/ && $l =~ /\bmemset\s*\(/; 52 | push @{$troubles->{unwanted_memcpy}}, $lineno if $file =~ /^src\/.*\.c$/ && $l =~ /\bmemcpy\s*\(/; 53 | push @{$troubles->{unwanted_memmove}}, $lineno if $file =~ /^src\/.*\.c$/ && $l =~ /\bmemmove\s*\(/; 54 | push @{$troubles->{unwanted_memcmp}}, $lineno if $file =~ /^src\/.*\.c$/ && $l =~ /\bmemcmp\s*\(/; 55 | push @{$troubles->{unwanted_strcmp}}, $lineno if $file =~ /^src\/.*\.c$/ && $l =~ /\bstrcmp\s*\(/; 56 | push @{$troubles->{unwanted_strcpy}}, $lineno if $file =~ /^src\/.*\.c$/ && $l =~ /\bstrcpy\s*\(/; 57 | push @{$troubles->{unwanted_strlen}}, $lineno if $file =~ /^src\/.*\.c$/ && $l =~ /\bstrlen\s*\(/; 58 | push @{$troubles->{unwanted_strncpy}}, $lineno if $file =~ /^src\/.*\.c$/ && $l =~ /\bstrncpy\s*\(/; 59 | push @{$troubles->{unwanted_clock}}, $lineno if $file =~ /^src\/.*\.c$/ && $l =~ /\bclock\s*\(/; 60 | push @{$troubles->{unwanted_qsort}}, $lineno if $file =~ /^src\/.*\.c$/ && $l =~ /\bqsort\s*\(/; 61 | push @{$troubles->{sizeof_no_brackets}}, $lineno if $file =~ /^src\/.*\.c$/ && $l =~ /\bsizeof\s*[^\(]/; 62 | if ($file =~ m|src/.*\.c$| && 63 | $l =~ /^static(\s+[a-zA-Z0-9_]+)+\s++([^s][a-zA-Z0-9_]+)\s*\(/) { 64 | push @{$troubles->{staticfunc_name}}, "$2"; 65 | } 66 | if ($file =~ m|src/.*\.[ch]$| && $l =~ /^\s*#\s*define\s+(_[A-Z_][a-zA-Z0-9_]*)\b/) { 67 | my $n = $1; 68 | push @{$troubles->{invalid_macro_name}}, "$lineno($n)"; 69 | } 70 | $lineno++; 71 | } 72 | for my $k (sort keys %$troubles) { 73 | warn "[$k] $file line:" . join(",", @{$troubles->{$k}}) . "\n"; 74 | $fails++; 75 | } 76 | } 77 | 78 | warn( $fails > 0 ? "check-source: FAIL $fails\n" : "check-source: PASS\n" ); 79 | return $fails; 80 | } 81 | 82 | sub check_comments { 83 | my $fails = 0; 84 | my $first_comment = <<'MARKER'; 85 | /* TomsFastMath, a fast ISO C bignum library. -- Tom St Denis */ 86 | /* SPDX-License-Identifier: Unlicense */ 87 | MARKER 88 | my @all_files; 89 | find({ wanted=> sub { push @all_files, $_ if $_ =~ /\.(c|h)$/ }, no_chdir=>1 }, 'demo', 'src'); 90 | for my $f (@all_files) { 91 | my $txt = read_file($f); 92 | if ($txt !~ /^\Q$first_comment\E/s) { 93 | warn "[first_comment] $f\n"; 94 | $fails++; 95 | } 96 | } 97 | warn( $fails > 0 ? "check-comments: FAIL $fails\n" : "check-comments: PASS\n" ); 98 | return $fails; 99 | } 100 | 101 | sub prepare_variable { 102 | my ($varname, @list) = @_; 103 | my $output = "$varname="; 104 | my $len = length($output); 105 | foreach my $obj (sort @list) { 106 | $len = $len + length $obj; 107 | $obj =~ s/\*/\$/; 108 | if ($len > 100) { 109 | $output .= "\\\n"; 110 | $len = length $obj; 111 | } 112 | $output .= $obj . ' '; 113 | } 114 | $output =~ s/ $//; 115 | return $output; 116 | } 117 | 118 | sub patch_file { 119 | my ($content, @variables) = @_; 120 | for my $v (@variables) { 121 | if ($v =~ /^([A-Z0-9_]+)\s*=.*$/si) { 122 | my $name = $1; 123 | $content =~ s/\n\Q$name\E\b.*?[^\\]\n/\n$v\n/s; 124 | } 125 | else { 126 | die "patch_file failed: " . substr($v, 0, 30) . ".."; 127 | } 128 | } 129 | return $content; 130 | } 131 | 132 | sub version_from_tfm_h { 133 | my $h = read_file(shift); 134 | if ($h =~ /\n#define\s*TFM_VERSION_S\s*"v([0-9]+)\.([0-9]+)\.([0-9]+)(\S*)"/s) { 135 | return "VERSION_PC=$1.$2.$3", "VERSION_LT=1:1", "VERSION=$1.$2.$3$4", "PROJECT_NUMBER=$1.$2.$3$4"; 136 | } 137 | else { 138 | die "#define TFM_VERSION_S not found in tfm.h"; 139 | } 140 | } 141 | 142 | sub make_sources_cmake { 143 | my ($list, $pub_headers) = @_; 144 | my $output = "set(SOURCES\n"; 145 | 146 | foreach my $obj (sort @$list) { 147 | $output .= $obj . "\n"; 148 | } 149 | $output .= ")\n\n"; 150 | 151 | if ($pub_headers eq "") { 152 | return $output; 153 | } 154 | 155 | $output .= "set(PUBLIC_HEADERS\n"; 156 | 157 | foreach my $obj (sort @$pub_headers) { 158 | $output .= $obj . "\n"; 159 | } 160 | 161 | $output .= ")\n\nset(PRIVATE_HEADERS src/headers/tfm_private.h)\n"; 162 | $output .= "set_property(GLOBAL PROPERTY PUBLIC_HEADERS \$\{PUBLIC_HEADERS\}\)\n\n"; 163 | 164 | return $output; 165 | } 166 | 167 | sub process_makefiles { 168 | my $write = shift; 169 | my $changed_count = 0; 170 | my @c = (); 171 | find({ no_chdir => 1, wanted => sub { push @c, $_ if -f $_ && $_ =~ /\.c$/ && $_ !~ /.gen\.c$/ } }, 'src'); 172 | my @h = (); 173 | find({ no_chdir => 1, wanted => sub { push @h, $_ if -f $_ && $_ =~ /\.h$/ && $_ !~ /tfm_private.h$/ } }, 'src'); 174 | my @all = (); 175 | find({ no_chdir => 1, wanted => sub { push @all, $_ if -f $_ && $_ =~ /\.(c|h)$/ } }, 'src'); 176 | 177 | my @o = sort (map { my $x = $_; $x =~ s/\.c$/.o/; $x } @c); 178 | my $var_o = prepare_variable("OBJECTS", @o); 179 | my $var_h = prepare_variable("HEADERS_PUB", (sort @h)); 180 | (my $var_obj = $var_o) =~ s/\.o\b/.obj/sg; 181 | 182 | 183 | my @ver_version = version_from_tfm_h("src/headers/tfm.h"); 184 | 185 | # update OBJECTS + HEADERS in makefile* 186 | for my $m (qw/ makefile makefile.shared sources.cmake /) { 187 | my $old = read_file($m); 188 | my $new = $m eq 'sources.cmake' ? make_sources_cmake(\@c, \@h) 189 | : patch_file($old, $var_o, $var_h, @ver_version); 190 | 191 | if ($old ne $new) { 192 | write_file($m, $new) if $write; 193 | warn "changed: $m\n"; 194 | $changed_count++; 195 | } 196 | } 197 | 198 | if ($write) { 199 | return 0; # no failures 200 | } 201 | else { 202 | warn( $changed_count > 0 ? "check-makefiles: FAIL $changed_count\n" : "check-makefiles: PASS\n" ); 203 | return $changed_count; 204 | } 205 | } 206 | 207 | sub die_usage { 208 | die <<"MARKER"; 209 | usage: $0 -s OR $0 --check-source 210 | $0 -c OR $0 --check-descriptors 211 | $0 -d OR $0 --check-defines 212 | $0 -o OR $0 --check-comments 213 | $0 -m OR $0 --check-makefiles 214 | $0 -a OR $0 --check-all 215 | $0 -u OR $0 --update-makefiles 216 | $0 --fixupind crypt.ind 217 | MARKER 218 | } 219 | 220 | GetOptions( "s|check-source" => \my $check_source, 221 | "c|check-descriptors" => \my $check_descriptors, 222 | "d|check-defines" => \my $check_defines, 223 | "o|check-comments" => \my $check_comments, 224 | "m|check-makefiles" => \my $check_makefiles, 225 | "a|check-all" => \my $check_all, 226 | "u|update-makefiles" => \my $update_makefiles, 227 | "f|fixupind=s" => \my $fixupind, 228 | "h|help" => \my $help 229 | ) or die_usage; 230 | 231 | if ($fixupind) { 232 | my $txt = read_file($fixupind); 233 | $txt =~ s/^([^\n]*\n)/$1\n\\addcontentsline{toc}{chapter}{Index}\n/s; 234 | write_file($fixupind, $txt); 235 | exit 0; 236 | } 237 | 238 | my $failure; 239 | $failure ||= check_source() if $check_all || $check_source; 240 | $failure ||= check_defines() if $check_all || $check_defines; 241 | $failure ||= check_comments() if $check_all || $check_comments; 242 | $failure ||= process_makefiles(0) if $check_all || $check_makefiles; 243 | $failure ||= process_makefiles(1) if $update_makefiles; 244 | 245 | die_usage unless defined $failure; 246 | exit $failure ? 1 : 0; 247 | 248 | # ref: HEAD -> develop 249 | # git commit: b2b4d030cf12431946b3fc485847b2ca026278c1 250 | # commit time: 2025-02-24 17:12:09 +0100 251 | -------------------------------------------------------------------------------- /makefile: -------------------------------------------------------------------------------- 1 | # makefile for TomsFastMath, a fast ISO C bignum library. -- Tom St Denis 2 | # SPDX-License-Identifier: Unlicense 3 | 4 | ifndef LIBNAME 5 | LIBNAME=libtfm.a 6 | endif 7 | 8 | INSTALL_CMD = install 9 | UNINSTALL_CMD = rm 10 | 11 | 12 | include makefile_include.mk 13 | 14 | ifeq ($V,1) 15 | silent= 16 | else 17 | silent=@ 18 | endif 19 | 20 | ifeq ($(COVERAGE),1) 21 | CFLAGS += -fprofile-arcs -ftest-coverage 22 | LDFLAGS += -lgcov 23 | LIB_PRE = -Wl,--whole-archive 24 | LIB_POST = -Wl,--no-whole-archive 25 | endif 26 | 27 | %.o: %.c 28 | ifneq ($V,1) 29 | @echo " * ${CC} $@" 30 | endif 31 | ${silent} ${CC} ${CFLAGS} -c $< -o $@ 32 | 33 | #START_INS 34 | OBJECTS=src/addsub/fp_add.o src/addsub/fp_add_d.o src/addsub/fp_addmod.o src/addsub/fp_cmp.o \ 35 | src/addsub/fp_cmp_d.o src/addsub/fp_cmp_mag.o src/addsub/fp_sub.o src/addsub/fp_sub_d.o \ 36 | src/addsub/fp_submod.o src/addsub/s_fp_add.o src/addsub/s_fp_sub.o src/bin/fp_radix_size.o \ 37 | src/bin/fp_read_radix.o src/bin/fp_read_signed_bin.o src/bin/fp_read_unsigned_bin.o \ 38 | src/bin/fp_reverse.o src/bin/fp_s_rmap.o src/bin/fp_signed_bin_size.o src/bin/fp_to_signed_bin.o \ 39 | src/bin/fp_to_unsigned_bin.o src/bin/fp_toradix.o src/bin/fp_toradix_n.o src/bin/fp_unsigned_bin_size.o \ 40 | src/bit/fp_cnt_lsb.o src/bit/fp_count_bits.o src/bit/fp_div_2.o src/bit/fp_div_2d.o src/bit/fp_lshd.o \ 41 | src/bit/fp_mod_2d.o src/bit/fp_rshd.o src/divide/fp_div.o src/divide/fp_div_d.o src/divide/fp_mod.o \ 42 | src/divide/fp_mod_d.o src/exptmod/fp_2expt.o src/exptmod/fp_exptmod.o src/misc/fp_ident.o \ 43 | src/misc/fp_rand.o src/misc/fp_set.o src/mont/fp_montgomery_calc_normalization.o \ 44 | src/mont/fp_montgomery_reduce.o src/mont/fp_montgomery_setup.o src/mul/fp_mul.o src/mul/fp_mul_2.o \ 45 | src/mul/fp_mul_2d.o src/mul/fp_mul_comba.o src/mul/fp_mul_comba_12.o src/mul/fp_mul_comba_17.o \ 46 | src/mul/fp_mul_comba_20.o src/mul/fp_mul_comba_24.o src/mul/fp_mul_comba_28.o src/mul/fp_mul_comba_3.o \ 47 | src/mul/fp_mul_comba_32.o src/mul/fp_mul_comba_4.o src/mul/fp_mul_comba_48.o src/mul/fp_mul_comba_6.o \ 48 | src/mul/fp_mul_comba_64.o src/mul/fp_mul_comba_7.o src/mul/fp_mul_comba_8.o src/mul/fp_mul_comba_9.o \ 49 | src/mul/fp_mul_comba_small_set.o src/mul/fp_mul_d.o src/mul/fp_mulmod.o src/numtheory/fp_gcd.o \ 50 | src/numtheory/fp_invmod.o src/numtheory/fp_isprime.o src/numtheory/fp_isprime_ex.o \ 51 | src/numtheory/fp_lcm.o src/numtheory/fp_prime_miller_rabin.o src/numtheory/fp_prime_random_ex.o \ 52 | src/sqr/fp_sqr.o src/sqr/fp_sqr_comba.o src/sqr/fp_sqr_comba_12.o src/sqr/fp_sqr_comba_17.o \ 53 | src/sqr/fp_sqr_comba_20.o src/sqr/fp_sqr_comba_24.o src/sqr/fp_sqr_comba_28.o src/sqr/fp_sqr_comba_3.o \ 54 | src/sqr/fp_sqr_comba_32.o src/sqr/fp_sqr_comba_4.o src/sqr/fp_sqr_comba_48.o src/sqr/fp_sqr_comba_6.o \ 55 | src/sqr/fp_sqr_comba_64.o src/sqr/fp_sqr_comba_7.o src/sqr/fp_sqr_comba_8.o src/sqr/fp_sqr_comba_9.o \ 56 | src/sqr/fp_sqr_comba_generic.o src/sqr/fp_sqr_comba_small_set.o src/sqr/fp_sqrmod.o 57 | 58 | HEADERS_PUB=src/headers/tfm.h 59 | HEADERS=src/headers/tfm_private.h $(HEADERS_PUB) 60 | 61 | #END_INS 62 | 63 | $(OBJECTS): $(HEADERS) 64 | 65 | $(LIBNAME): $(OBJECTS) 66 | $(AR) $(ARFLAGS) $@ $(OBJECTS) 67 | $(RANLIB) $@ 68 | 69 | install: .common_install 70 | 71 | uninstall: .common_uninstall 72 | 73 | .PHONY: test 74 | test: $(LIBNAME) demo/test.o 75 | $(CC) $(CFLAGS) demo/test.o $(LIB_PRE) $(LIBNAME) $(LIB_POST) $(PROF) -o test 76 | 77 | test_standalone: CFLAGS+=-DTFM_DEMO_TEST_VS_MTEST=0 78 | 79 | .PHONY: test_standalone 80 | test_standalone: $(LIBNAME) demo/test.o 81 | $(CC) $(CFLAGS) demo/test.o $(LIB_PRE) $(LIBNAME) $(LIB_POST) $(PROF) -o test 82 | 83 | testme: test mtest 84 | ./mtest/mtest -15 | ./test 85 | 86 | timing: $(LIBNAME) demo/timing.o 87 | $(CC) $(CFLAGS) demo/timing.o $(LIBNAME) $(PROF) -o timing 88 | 89 | ident: $(LIBNAME) 90 | $(CC) $(CFLAGS) -DSTANDALONE src/misc/fp_ident.c $(LIBNAME) $(PROF) -o ident 91 | 92 | profiled: 93 | CC="$(CC)" CROSS_COMPILE="${CROSS_COMPILE} CFLAGS="${CFLAGS} -fprofile-generate" MAKE=${MAKE} ${MAKE} timing 94 | ./test 95 | rm -f `find . -type f -name "*.o" | xargs` 96 | rm -f `find . -type f -name "*.a" | xargs` 97 | rm -f test 98 | CC=$(CC) CROSS_COMPILE="${CROSS_COMPILE} CFLAGS="${CFLAGS} -fprofile-use" MAKE=${MAKE} ${MAKE} timing 99 | 100 | # target that pre-processes all coverage data 101 | lcov-single-create: 102 | lcov --capture --no-external --directory src -q --output-file coverage_std.info 103 | 104 | # target that removes all coverage output 105 | cleancov-clean: 106 | rm -f `find . -type f -name "*.info" | xargs` 107 | rm -rf coverage/ 108 | 109 | # generates html output from all coverage_*.info files 110 | lcov: 111 | lcov `find -name 'coverage_*.info' -exec echo -n " -a {}" \;` -o coverage.info -q 2>/dev/null 112 | genhtml coverage.info --output-directory coverage -q 113 | 114 | # combines all necessary steps to create the coverage from a single testrun with e.g. 115 | lcov-single: 116 | $(MAKE) cleancov-clean 117 | $(MAKE) lcov-single-create 118 | $(MAKE) lcov 119 | 120 | 121 | #make the code coverage of the library 122 | coverage: CFLAGS += -fprofile-arcs -ftest-coverage 123 | coverage: LDFLAGS += -lgcov 124 | coverage: LIB_PRE = -Wl,--whole-archive 125 | coverage: LIB_POST = -Wl,--no-whole-archive 126 | 127 | coverage: testme 128 | $(MAKE) lcov-single 129 | 130 | stest: $(LIBNAME) demo/stest.o 131 | $(CC) $(CFLAGS) demo/stest.o $(LIBNAME) -o stest 132 | 133 | amalgamated_stest: amalgam 134 | $(CC) $(CFLAGS) demo/stest.c pre_gen/tfm_amalgam.c -o stest 135 | 136 | rsatest: $(LIBNAME) demo/rsa.o 137 | $(CC) $(CFLAGS) demo/rsa.o $(LIBNAME) -o rsatest 138 | -------------------------------------------------------------------------------- /makefile.shared: -------------------------------------------------------------------------------- 1 | # makefile for TomsFastMath, a fast ISO C bignum library. -- Tom St Denis 2 | # SPDX-License-Identifier: Unlicense 3 | 4 | ifndef LIBNAME 5 | LIBNAME=libtfm.la 6 | endif 7 | 8 | LT ?= libtool 9 | LTCOMPILE = $(LT) --mode=compile --tag=CC $(CC) 10 | 11 | INSTALL_CMD = $(LT) --mode=install install 12 | UNINSTALL_CMD = $(LT) --mode=uninstall rm 13 | 14 | 15 | include makefile_include.mk 16 | 17 | #START_INS 18 | OBJECTS=src/addsub/fp_add.o src/addsub/fp_add_d.o src/addsub/fp_addmod.o src/addsub/fp_cmp.o \ 19 | src/addsub/fp_cmp_d.o src/addsub/fp_cmp_mag.o src/addsub/fp_sub.o src/addsub/fp_sub_d.o \ 20 | src/addsub/fp_submod.o src/addsub/s_fp_add.o src/addsub/s_fp_sub.o src/bin/fp_radix_size.o \ 21 | src/bin/fp_read_radix.o src/bin/fp_read_signed_bin.o src/bin/fp_read_unsigned_bin.o \ 22 | src/bin/fp_reverse.o src/bin/fp_s_rmap.o src/bin/fp_signed_bin_size.o src/bin/fp_to_signed_bin.o \ 23 | src/bin/fp_to_unsigned_bin.o src/bin/fp_toradix.o src/bin/fp_toradix_n.o src/bin/fp_unsigned_bin_size.o \ 24 | src/bit/fp_cnt_lsb.o src/bit/fp_count_bits.o src/bit/fp_div_2.o src/bit/fp_div_2d.o src/bit/fp_lshd.o \ 25 | src/bit/fp_mod_2d.o src/bit/fp_rshd.o src/divide/fp_div.o src/divide/fp_div_d.o src/divide/fp_mod.o \ 26 | src/divide/fp_mod_d.o src/exptmod/fp_2expt.o src/exptmod/fp_exptmod.o src/misc/fp_ident.o \ 27 | src/misc/fp_rand.o src/misc/fp_set.o src/mont/fp_montgomery_calc_normalization.o \ 28 | src/mont/fp_montgomery_reduce.o src/mont/fp_montgomery_setup.o src/mul/fp_mul.o src/mul/fp_mul_2.o \ 29 | src/mul/fp_mul_2d.o src/mul/fp_mul_comba.o src/mul/fp_mul_comba_12.o src/mul/fp_mul_comba_17.o \ 30 | src/mul/fp_mul_comba_20.o src/mul/fp_mul_comba_24.o src/mul/fp_mul_comba_28.o src/mul/fp_mul_comba_3.o \ 31 | src/mul/fp_mul_comba_32.o src/mul/fp_mul_comba_4.o src/mul/fp_mul_comba_48.o src/mul/fp_mul_comba_6.o \ 32 | src/mul/fp_mul_comba_64.o src/mul/fp_mul_comba_7.o src/mul/fp_mul_comba_8.o src/mul/fp_mul_comba_9.o \ 33 | src/mul/fp_mul_comba_small_set.o src/mul/fp_mul_d.o src/mul/fp_mulmod.o src/numtheory/fp_gcd.o \ 34 | src/numtheory/fp_invmod.o src/numtheory/fp_isprime.o src/numtheory/fp_isprime_ex.o \ 35 | src/numtheory/fp_lcm.o src/numtheory/fp_prime_miller_rabin.o src/numtheory/fp_prime_random_ex.o \ 36 | src/sqr/fp_sqr.o src/sqr/fp_sqr_comba.o src/sqr/fp_sqr_comba_12.o src/sqr/fp_sqr_comba_17.o \ 37 | src/sqr/fp_sqr_comba_20.o src/sqr/fp_sqr_comba_24.o src/sqr/fp_sqr_comba_28.o src/sqr/fp_sqr_comba_3.o \ 38 | src/sqr/fp_sqr_comba_32.o src/sqr/fp_sqr_comba_4.o src/sqr/fp_sqr_comba_48.o src/sqr/fp_sqr_comba_6.o \ 39 | src/sqr/fp_sqr_comba_64.o src/sqr/fp_sqr_comba_7.o src/sqr/fp_sqr_comba_8.o src/sqr/fp_sqr_comba_9.o \ 40 | src/sqr/fp_sqr_comba_generic.o src/sqr/fp_sqr_comba_small_set.o src/sqr/fp_sqrmod.o 41 | 42 | LOBJECTS = $(OBJECTS:.o=.lo) 43 | 44 | HEADERS_PUB=src/headers/tfm.h 45 | HEADERS=src/headers/tfm_private.h $(HEADERS_PUB) 46 | 47 | #END_INS 48 | 49 | 50 | $(OBJECTS): $(HEADERS) 51 | 52 | .c.o: 53 | $(LTCOMPILE) $(CFLAGS) $(LDFLAGS) -o $@ -c $< 54 | 55 | $(LIBNAME): $(OBJECTS) 56 | $(LT) --mode=link --tag=CC $(CC) $(CFLAGS) $(LDFLAGS) $(LOBJECTS) -o $(LIBNAME) -rpath $(LIBPATH) -version-info $(VERSION_LIB) 57 | 58 | install: .common_install 59 | sed -e 's,^prefix=.*,prefix=$(PREFIX),' -e 's,^Version:.*,Version: $(VERSION_PC),' -e 's,@CMAKE_INSTALL_LIBDIR@,lib,' \ 60 | -e 's,@CMAKE_INSTALL_INCLUDEDIR@/@PROJECT_NAME@,include/tomsfastmath,' tomsfastmath.pc.in > tomsfastmath.pc 61 | install -d $(DESTDIR)$(LIBPATH)/pkgconfig 62 | install -m 644 tomsfastmath.pc $(DESTDIR)$(LIBPATH)/pkgconfig/ 63 | 64 | uninstall: .common_uninstall 65 | rm $(DESTDIR)$(LIBPATH)/pkgconfig/tomsfastmath.pc 66 | 67 | .PHONY: test 68 | test: $(LIBNAME) demo/test.o 69 | $(LT) --mode=link --tag=CC $(CC) $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) -o test demo/test.o $(LIBNAME) 70 | 71 | test_standalone: CFLAGS+=-DTFM_DEMO_TEST_VS_MTEST=0 72 | 73 | .PHONY: test_standalone 74 | test_standalone: $(LIBNAME) demo/test.o 75 | $(LT) --mode=link --tag=CC $(CC) $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) -o test demo/test.o $(LIBNAME) 76 | 77 | stest: $(LIBNAME) demo/stest.o 78 | $(LT) --mode=link --tag=CC $(CC) $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) -o stest demo/stest.o $(LIBNAME) 79 | 80 | .PHONY: timing 81 | timing: $(LIBNAME) demo/timing.o 82 | $(LT) --mode=link --tag=CC $(CC) $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) -o timing demo/timing.o $(LIBNAME) 83 | -------------------------------------------------------------------------------- /makefile_include.mk: -------------------------------------------------------------------------------- 1 | # 2 | # Include makefile used by makefile + makefile.shared 3 | # (GNU make only) 4 | # SPDX-License-Identifier: Unlicense 5 | 6 | ifndef INSTALL_CMD 7 | $(error your makefile must define INSTALL_CMD) 8 | endif 9 | ifndef UNINSTALL_CMD 10 | $(error your makefile must define UNINSTALL_CMD) 11 | endif 12 | 13 | # 14 | # The Version of the library 15 | # 16 | VERSION=0.13.1-next 17 | VERSION_LIB=1:0:0 18 | VERSION_PC=0.13.1 19 | 20 | GIT_VERSION := $(shell [ -e .git ] && { printf git- ; git describe --tags --always --dirty ; } || echo $(VERSION)) 21 | ifneq ($(GIT_VERSION),) 22 | CFLAGS += -DGIT_VERSION=\"$(GIT_VERSION)\" 23 | endif 24 | 25 | # Compiler and Linker Names 26 | ifndef CROSS_COMPILE 27 | CROSS_COMPILE:= 28 | endif 29 | 30 | ifeq ($(CC),cc) 31 | CC := $(CROSS_COMPILE)gcc 32 | endif 33 | LD:=$(CROSS_COMPILE)ld 34 | AR:=$(CROSS_COMPILE)ar 35 | RANLIB=$(CROSS_COMPILE)ranlib 36 | 37 | ifndef MAKE 38 | MAKE=make 39 | endif 40 | 41 | # 42 | # Compilation flags 43 | # 44 | # Note that we're extending the environments' CFLAGS. 45 | # If you think that our CFLAGS are not nice you can easily override them 46 | # by giving them as a parameter to make: 47 | # make CFLAGS="-I./src/headers/ -DLTC_SOURCE ..." ... 48 | # 49 | 50 | CFLAGS += -Wall -W -Wshadow -Isrc/headers 51 | 52 | ifdef COMPILE_DEBUG 53 | #debug 54 | CFLAGS += -g3 55 | else 56 | ifndef IGNORE_SPEED 57 | 58 | CFLAGS += -O3 59 | 60 | PLATFORM := $(shell uname | sed -e 's/_.*//') 61 | ifneq ($(PLATFORM), Darwin) 62 | CFLAGS += -funroll-loops 63 | endif 64 | 65 | #profiling 66 | #PROF=-pg -g 67 | #CFLAGS += $(PROF) 68 | 69 | #speed 70 | CFLAGS += -fomit-frame-pointer 71 | 72 | endif 73 | endif 74 | 75 | # 76 | # (Un)Install related variables 77 | # 78 | DESTDIR ?= 79 | PREFIX ?= /usr/local 80 | LIBPATH ?= $(PREFIX)/lib 81 | INCPATH ?= $(PREFIX)/include 82 | 83 | 84 | # 85 | # Build targets 86 | # 87 | 88 | default: $(LIBNAME) 89 | 90 | 91 | demo/test.o: CFLAGS+=-Wno-unused-result 92 | 93 | .PHONY: mtest 94 | mtest: $(LIBNAME) 95 | CC="$(CC)" CFLAGS="$(CFLAGS) -I../" MAKE=${MAKE} ${MAKE} -C mtest/ mtest 96 | 97 | .common_install: $(LIBNAME) 98 | install -d $(DESTDIR)$(LIBPATH) 99 | $(INSTALL_CMD) $(LIBNAME) $(DESTDIR)$(LIBPATH)/$(LIBNAME) 100 | install -d $(DESTDIR)$(INCPATH) 101 | install $(HEADERS_PUB) $(DESTDIR)$(INCPATH)/tomsfastmath 102 | 103 | 104 | HEADER_FILES=$(notdir $(HEADERS_PUB)) 105 | .common_uninstall: 106 | $(UNINSTALL_CMD) $(DESTDIR)$(LIBPATH)/$(LIBNAME) 107 | rm $(HEADER_FILES:%=$(DESTDIR)$(INCPATH)/%) 108 | 109 | 110 | #This rule cleans the source tree of all compiled code, not including the pdf 111 | #documentation. 112 | clean: 113 | find . -type f -name "*.o" \ 114 | -o -name "*.lo" \ 115 | -o -name "*.a" \ 116 | -o -name "*.la" \ 117 | -o -name "*.obj" \ 118 | -o -name "*.lib" \ 119 | -o -name "*.exe" \ 120 | -o -name "*.dll" \ 121 | -o -name "*.so" \ 122 | -o -name "*.gcov"\ 123 | -o -name "*.gcda"\ 124 | -o -name "*.gcno"\ 125 | -o -name "*.il" \ 126 | -o -name "*.dyn" \ 127 | -o -name "*.dpi" | xargs rm -f 128 | find . -type d -name "*.libs" | xargs rm -rf 129 | rm -f tfm.aux tfm.dvi tfm.idx tfm.ilg tfm.ind tfm.lof tfm.log tfm.out tfm.toc test test.exe 130 | cd mtest; MAKE=${MAKE} ${MAKE} clean 131 | 132 | docs: 133 | $(MAKE) -C doc/ $@ V=$(V) 134 | 135 | doc/tfm.pdf: 136 | $(MAKE) -C doc/ tfm.pdf V=$(V) 137 | 138 | 139 | SOURCES = $(OBJECTS:.o=.c) 140 | pre_gen/tfm_amalgam.c: $(SOURCES) 141 | mkdir -p pre_gen 142 | @printf "\ 143 | /* TomsFastMath, a fast ISO C bignum library. -- Tom St Denis */\n\ 144 | /* SPDX-License-Identifier: Unlicense */\n\ 145 | \n\ 146 | /*** AUTO-GENERATED FILE! DO NOT EDIT MANUALLY ***/\n\ 147 | \n\ 148 | #define TFM_PRE_GEN_MPI_C\n\ 149 | \n" > $@ 150 | cat $(SOURCES) >> $@ 151 | 152 | amalgam pre_gen: pre_gen/tfm_amalgam.c 153 | 154 | zipup: doc/tfm.pdf 155 | @# Update the index, so diff-index won't fail in case the pdf has been created. 156 | @# As the pdf creation modifies tfm.tex, git sometimes detects the 157 | @# modified file, but misses that it's put back to its original version. 158 | @git update-index --refresh 159 | @git diff-index --quiet HEAD -- || ( echo "FAILURE: uncommited changes or not a git" && exit 1 ) 160 | rm -rf tomsfastmath-$(VERSION) tfm-$(VERSION).* 161 | @# files/dirs excluded from "git archive" are defined in .gitattributes 162 | git archive --format=tar --prefix=tomsfastmath-$(VERSION)/ HEAD | tar x 163 | mkdir -p tomsfastmath-$(VERSION)/doc 164 | cp doc/tfm.pdf tomsfastmath-$(VERSION)/doc/tfm.pdf 165 | $(MAKE) -C tomsfastmath-$(VERSION)/ pre_gen 166 | tar -c tomsfastmath-$(VERSION)/ | xz -6e -c - > tfm-$(VERSION).tar.xz 167 | zip -9rq tfm-$(VERSION).zip tomsfastmath-$(VERSION) 168 | rm -rf tomsfastmath-$(VERSION) 169 | gpg -b -a tfm-$(VERSION).tar.xz 170 | gpg -b -a tfm-$(VERSION).zip 171 | 172 | new_file: 173 | bash updatemakes.sh 174 | 175 | .PHONY: doc/tfm.pdf 176 | -------------------------------------------------------------------------------- /mtest/makefile: -------------------------------------------------------------------------------- 1 | # TomsFastMath, a fast ISO C bignum library. -- Tom St Denis 2 | # SPDX-License-Identifier: Unlicense 3 | 4 | CFLAGS += -Wall -W -O3 -Wno-unused-result 5 | 6 | default: mtest 7 | 8 | .PHONY: mtest 9 | mtest: mtest.o 10 | $(CC) $(CFLAGS) mtest.o -ltommath -o mtest 11 | 12 | clean: 13 | rm -f *.o mtest *~ mtest.exe 14 | -------------------------------------------------------------------------------- /random_txt_files/amd64.txt: -------------------------------------------------------------------------------- 1 | AMD64 timings 2 | 3 | using ISO C 4 | mult 5 | 512-bit: 496 6 | 1024-bit: 1717 7 | 2048-bit: 7200 8 | sqr 9 | 512-bit: 448 10 | 1024-bit: 1760 11 | 2048-bit: 7099 12 | mont 13 | 512-bit: 1416 14 | 1024-bit: 5156 15 | 2048-bit: 20820 16 | expt 17 | 512-bit: 1520207 18 | 1024-bit: 10603520 19 | 2048-bit: 84893649 20 | 21 | using amd64 22 | mult 23 | 512-bit: 292 24 | 1024-bit: 945 25 | 2048-bit: 3620 26 | sqr 27 | 512-bit: 238 28 | 1024-bit: 801 29 | 2048-bit: 2853 30 | mont 31 | 512-bit: 731 32 | 1024-bit: 1730 33 | 2048-bit: 5462 34 | Exptmod: 35 | 512-bit: 641743 36 | 1024-bit: 3167406 37 | 2048-bit: 20158609 38 | 39 | LTM exptmods 40 | 41 | Exponentiating 513-bit => 825/sec, 2183028 cycles 42 | Exponentiating 1025-bit => 151/sec, 11900720 cycles 43 | Exponentiating 2049-bit => 24/sec, 72376416 cycles 44 | -------------------------------------------------------------------------------- /random_txt_files/exptmod_timings.txt: -------------------------------------------------------------------------------- 1 | LTM timings: 2 | 3 | Athlon Barton 4 | Exponentiating 513-bit => 561/sec, 3909824 cycles 5 | Exponentiating 1025-bit => 103/sec, 21175496 cycles 6 | Exponentiating 2049-bit => 16/sec, 129845554 cycles 7 | 8 | P4 Northwood 9 | Exponentiating 513-bit => 284/sec, 9884722 cycles 10 | Exponentiating 1025-bit => 47/sec, 59090432 cycles 11 | Exponentiating 2049-bit => 6/sec, 427456070 cycles 12 | 13 | TFM timings: 14 | 15 | Athlon Barton 16 | 512-bit: 2289257 17 | 1024-bit: 12871373 18 | 2048-bit: 97211357 19 | 20 | P4 Northwood [x86-32] 21 | 512-bit: 8015598 22 | 1024-bit: 55559304 23 | 2048-bit: 409861746 24 | 25 | P4 Northwood [SSE2] 26 | 512-bit: 5895000 27 | 1024-bit: 39648730 28 | 2048-bit: 304110670 29 | 30 |
31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 |
ProcessorSize in bitsx86-32 x86-64SSE2LTM
P4 512 8015598 58950009884722
1024 55559304 3964873059090432
2048 409861746 304110670427456070
Athlon Barton512 22892573909824
1024 1287137321175496
2048 97211357129845554
Athlon64 512 6417432183028
1042 316740611900720
2048 2015860972376416
43 | Cycles per operation 44 |
45 | 46 | -------------------------------------------------------------------------------- /random_txt_files/ltm_times.txt: -------------------------------------------------------------------------------- 1 | LTM Timings... 2 | 3 | Multiplying 140-bit => 2950763/sec, 952 cycles 4 | Multiplying 196-bit => 2150939/sec, 1306 cycles 5 | Multiplying 252-bit => 1357066/sec, 2070 cycles 6 | Multiplying 308-bit => 1055269/sec, 2662 cycles 7 | Multiplying 364-bit => 817557/sec, 3436 cycles 8 | Multiplying 420-bit => 636413/sec, 4414 cycles 9 | Multiplying 475-bit => 536912/sec, 5232 cycles 10 | Multiplying 531-bit => 433641/sec, 6478 cycles 11 | Multiplying 588-bit => 372069/sec, 7550 cycles 12 | Multiplying 644-bit => 322813/sec, 8702 cycles 13 | Multiplying 698-bit => 275566/sec, 10194 cycles 14 | Multiplying 753-bit => 242082/sec, 11604 cycles 15 | Multiplying 809-bit => 214797/sec, 13078 cycles 16 | Multiplying 867-bit => 189626/sec, 14814 cycles 17 | Multiplying 921-bit => 168858/sec, 16636 cycles 18 | Multiplying 978-bit => 151598/sec, 18530 cycles 19 | Multiplying 1036-bit => 137580/sec, 20418 cycles 20 | Multiplying 1091-bit => 124661/sec, 22534 cycles 21 | Multiplying 1148-bit => 111677/sec, 25154 cycles 22 | Multiplying 1199-bit => 102762/sec, 27336 cycles 23 | Multiplying 1258-bit => 94519/sec, 29720 cycles 24 | Multiplying 1316-bit => 86975/sec, 32298 cycles 25 | Multiplying 1371-bit => 79754/sec, 35222 cycles 26 | Multiplying 1427-bit => 74473/sec, 37720 cycles 27 | Multiplying 1483-bit => 68827/sec, 40814 cycles 28 | Multiplying 1537-bit => 63644/sec, 44138 cycles 29 | Multiplying 1595-bit => 59646/sec, 47096 cycles 30 | Multiplying 1651-bit => 56469/sec, 49746 cycles 31 | Multiplying 1708-bit => 52640/sec, 53364 cycles 32 | Multiplying 1764-bit => 49823/sec, 56382 cycles 33 | Multiplying 1819-bit => 46856/sec, 59952 cycles 34 | Multiplying 1875-bit => 44264/sec, 63462 cycles 35 | Multiplying 1929-bit => 41641/sec, 67460 cycles 36 | Multiplying 1985-bit => 39539/sec, 71046 cycles 37 | Multiplying 2044-bit => 37591/sec, 74728 cycles -------------------------------------------------------------------------------- /random_txt_files/newsqr.txt: -------------------------------------------------------------------------------- 1 | New code added in TFM v0.03 2 | 3 | OLD 64-bit...[athlon64] 4 | 5 | Squaring: 6 | 256-bit: 89 7 | 512-bit: 234 8 | 1024-bit: 815 9 | 2048-bit: 2851 10 | 11 | NEW 64-bit ... 12 | 13 | Squaring: 14 | 256-bit: 89 15 | 512-bit: 228 16 | 1024-bit: 691 17 | 2048-bit: 2228 18 | 19 | 20 | OLD 32-bit [athlonxp] 21 | 22 | Squaring: 23 | 24 | 256-bit: 327 25 | 512-bit: 1044 26 | 1024-bit: 3646 27 | 2048-bit: 17055 28 | 29 | NEW 32-bit 30 | 31 | Squaring: 32 | 33 | 256-bit: 332 34 | 512-bit: 894 35 | 1024-bit: 2983 36 | 2048-bit: 10385 37 | -------------------------------------------------------------------------------- /random_txt_files/old_sqr_times.txt: -------------------------------------------------------------------------------- 1 | I started with: 2 | 512-bit: 16338 3 | 1024-bit: 51020 4 | 2048-bit: 142718 5 | 6 | My x86-32 7 | 512-bit: 2864 8 | 1024-bit: 10615 9 | 2048-bit: 41807 10 | 11 | My SSE2 12 | 512-bit: 2168 13 | 1024-bit: 7727 14 | 2048-bit: 33163 -------------------------------------------------------------------------------- /sources.cmake: -------------------------------------------------------------------------------- 1 | set(SOURCES 2 | src/addsub/fp_add.c 3 | src/addsub/fp_add_d.c 4 | src/addsub/fp_addmod.c 5 | src/addsub/fp_cmp.c 6 | src/addsub/fp_cmp_d.c 7 | src/addsub/fp_cmp_mag.c 8 | src/addsub/fp_sub.c 9 | src/addsub/fp_sub_d.c 10 | src/addsub/fp_submod.c 11 | src/addsub/s_fp_add.c 12 | src/addsub/s_fp_sub.c 13 | src/bin/fp_radix_size.c 14 | src/bin/fp_read_radix.c 15 | src/bin/fp_read_signed_bin.c 16 | src/bin/fp_read_unsigned_bin.c 17 | src/bin/fp_reverse.c 18 | src/bin/fp_s_rmap.c 19 | src/bin/fp_signed_bin_size.c 20 | src/bin/fp_to_signed_bin.c 21 | src/bin/fp_to_unsigned_bin.c 22 | src/bin/fp_toradix.c 23 | src/bin/fp_toradix_n.c 24 | src/bin/fp_unsigned_bin_size.c 25 | src/bit/fp_cnt_lsb.c 26 | src/bit/fp_count_bits.c 27 | src/bit/fp_div_2.c 28 | src/bit/fp_div_2d.c 29 | src/bit/fp_lshd.c 30 | src/bit/fp_mod_2d.c 31 | src/bit/fp_rshd.c 32 | src/divide/fp_div.c 33 | src/divide/fp_div_d.c 34 | src/divide/fp_mod.c 35 | src/divide/fp_mod_d.c 36 | src/exptmod/fp_2expt.c 37 | src/exptmod/fp_exptmod.c 38 | src/misc/fp_ident.c 39 | src/misc/fp_rand.c 40 | src/misc/fp_set.c 41 | src/mont/fp_montgomery_calc_normalization.c 42 | src/mont/fp_montgomery_reduce.c 43 | src/mont/fp_montgomery_setup.c 44 | src/mul/fp_mul.c 45 | src/mul/fp_mul_2.c 46 | src/mul/fp_mul_2d.c 47 | src/mul/fp_mul_comba.c 48 | src/mul/fp_mul_comba_12.c 49 | src/mul/fp_mul_comba_17.c 50 | src/mul/fp_mul_comba_20.c 51 | src/mul/fp_mul_comba_24.c 52 | src/mul/fp_mul_comba_28.c 53 | src/mul/fp_mul_comba_3.c 54 | src/mul/fp_mul_comba_32.c 55 | src/mul/fp_mul_comba_4.c 56 | src/mul/fp_mul_comba_48.c 57 | src/mul/fp_mul_comba_6.c 58 | src/mul/fp_mul_comba_64.c 59 | src/mul/fp_mul_comba_7.c 60 | src/mul/fp_mul_comba_8.c 61 | src/mul/fp_mul_comba_9.c 62 | src/mul/fp_mul_comba_small_set.c 63 | src/mul/fp_mul_d.c 64 | src/mul/fp_mulmod.c 65 | src/numtheory/fp_gcd.c 66 | src/numtheory/fp_invmod.c 67 | src/numtheory/fp_isprime.c 68 | src/numtheory/fp_isprime_ex.c 69 | src/numtheory/fp_lcm.c 70 | src/numtheory/fp_prime_miller_rabin.c 71 | src/numtheory/fp_prime_random_ex.c 72 | src/sqr/fp_sqr.c 73 | src/sqr/fp_sqr_comba.c 74 | src/sqr/fp_sqr_comba_12.c 75 | src/sqr/fp_sqr_comba_17.c 76 | src/sqr/fp_sqr_comba_20.c 77 | src/sqr/fp_sqr_comba_24.c 78 | src/sqr/fp_sqr_comba_28.c 79 | src/sqr/fp_sqr_comba_3.c 80 | src/sqr/fp_sqr_comba_32.c 81 | src/sqr/fp_sqr_comba_4.c 82 | src/sqr/fp_sqr_comba_48.c 83 | src/sqr/fp_sqr_comba_6.c 84 | src/sqr/fp_sqr_comba_64.c 85 | src/sqr/fp_sqr_comba_7.c 86 | src/sqr/fp_sqr_comba_8.c 87 | src/sqr/fp_sqr_comba_9.c 88 | src/sqr/fp_sqr_comba_generic.c 89 | src/sqr/fp_sqr_comba_small_set.c 90 | src/sqr/fp_sqrmod.c 91 | ) 92 | 93 | set(PUBLIC_HEADERS 94 | src/headers/tfm.h 95 | ) 96 | 97 | set(PRIVATE_HEADERS src/headers/tfm_private.h) 98 | set_property(GLOBAL PROPERTY PUBLIC_HEADERS ${PUBLIC_HEADERS}) 99 | 100 | -------------------------------------------------------------------------------- /src/addsub/fp_add.c: -------------------------------------------------------------------------------- 1 | /* TomsFastMath, a fast ISO C bignum library. -- Tom St Denis */ 2 | /* SPDX-License-Identifier: Unlicense */ 3 | #include 4 | 5 | void fp_add(const fp_int *a, const fp_int *b, fp_int *c) 6 | { 7 | int sa, sb; 8 | 9 | /* get sign of both inputs */ 10 | sa = a->sign; 11 | sb = b->sign; 12 | 13 | /* handle two cases, not four */ 14 | if (sa == sb) { 15 | /* both positive or both negative */ 16 | /* add their magnitudes, copy the sign */ 17 | c->sign = sa; 18 | s_fp_add (a, b, c); 19 | } else { 20 | /* one positive, the other negative */ 21 | /* subtract the one with the greater magnitude from */ 22 | /* the one of the lesser magnitude. The result gets */ 23 | /* the sign of the one with the greater magnitude. */ 24 | if (fp_cmp_mag (a, b) == FP_LT) { 25 | c->sign = sb; 26 | s_fp_sub (b, a, c); 27 | } else { 28 | c->sign = sa; 29 | s_fp_sub (a, b, c); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/addsub/fp_add_d.c: -------------------------------------------------------------------------------- 1 | /* TomsFastMath, a fast ISO C bignum library. -- Tom St Denis */ 2 | /* SPDX-License-Identifier: Unlicense */ 3 | #include 4 | 5 | /* c = a + b */ 6 | void fp_add_d(const fp_int *a, fp_digit b, fp_int *c) 7 | { 8 | fp_int tmp; 9 | fp_set(&tmp, b); 10 | fp_add(a,&tmp,c); 11 | } 12 | -------------------------------------------------------------------------------- /src/addsub/fp_addmod.c: -------------------------------------------------------------------------------- 1 | /* TomsFastMath, a fast ISO C bignum library. -- Tom St Denis */ 2 | /* SPDX-License-Identifier: Unlicense */ 3 | #include 4 | 5 | /* d = a + b (mod c) */ 6 | int fp_addmod(const fp_int *a, const fp_int *b, const fp_int *c, fp_int *d) 7 | { 8 | fp_int tmp; 9 | fp_zero(&tmp); 10 | fp_add(a, b, &tmp); 11 | return fp_mod(&tmp, c, d); 12 | } 13 | -------------------------------------------------------------------------------- /src/addsub/fp_cmp.c: -------------------------------------------------------------------------------- 1 | /* TomsFastMath, a fast ISO C bignum library. -- Tom St Denis */ 2 | /* SPDX-License-Identifier: Unlicense */ 3 | #include 4 | 5 | int fp_cmp(const fp_int *a, const fp_int *b) 6 | { 7 | if (a->sign == FP_NEG && b->sign == FP_ZPOS) { 8 | return FP_LT; 9 | } else if (a->sign == FP_ZPOS && b->sign == FP_NEG) { 10 | return FP_GT; 11 | } else { 12 | /* compare digits */ 13 | if (a->sign == FP_NEG) { 14 | /* if negative compare opposite direction */ 15 | return fp_cmp_mag(b, a); 16 | } else { 17 | return fp_cmp_mag(a, b); 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/addsub/fp_cmp_d.c: -------------------------------------------------------------------------------- 1 | /* TomsFastMath, a fast ISO C bignum library. -- Tom St Denis */ 2 | /* SPDX-License-Identifier: Unlicense */ 3 | #include 4 | 5 | /* compare against a single digit */ 6 | int fp_cmp_d(const fp_int *a, fp_digit b) 7 | { 8 | /* compare based on sign */ 9 | if ((b && a->used == 0) || a->sign == FP_NEG) { 10 | return FP_LT; 11 | } 12 | 13 | /* compare based on magnitude */ 14 | if (a->used > 1) { 15 | return FP_GT; 16 | } 17 | 18 | /* compare the only digit of a to b */ 19 | if (a->dp[0] > b) { 20 | return FP_GT; 21 | } else if (a->dp[0] < b) { 22 | return FP_LT; 23 | } else { 24 | return FP_EQ; 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /src/addsub/fp_cmp_mag.c: -------------------------------------------------------------------------------- 1 | /* TomsFastMath, a fast ISO C bignum library. -- Tom St Denis */ 2 | /* SPDX-License-Identifier: Unlicense */ 3 | #include 4 | 5 | int fp_cmp_mag(const fp_int *a, const fp_int *b) 6 | { 7 | int x; 8 | 9 | if (a->used > b->used) { 10 | return FP_GT; 11 | } else if (a->used < b->used) { 12 | return FP_LT; 13 | } else { 14 | for (x = a->used - 1; x >= 0; x--) { 15 | if (a->dp[x] > b->dp[x]) { 16 | return FP_GT; 17 | } else if (a->dp[x] < b->dp[x]) { 18 | return FP_LT; 19 | } 20 | } 21 | } 22 | return FP_EQ; 23 | } 24 | -------------------------------------------------------------------------------- /src/addsub/fp_sub.c: -------------------------------------------------------------------------------- 1 | /* TomsFastMath, a fast ISO C bignum library. -- Tom St Denis */ 2 | /* SPDX-License-Identifier: Unlicense */ 3 | #include 4 | 5 | /* c = a - b */ 6 | void fp_sub(const fp_int *a, const fp_int *b, fp_int *c) 7 | { 8 | int sa, sb; 9 | 10 | sa = a->sign; 11 | sb = b->sign; 12 | 13 | if (sa != sb) { 14 | /* subtract a negative from a positive, OR */ 15 | /* subtract a positive from a negative. */ 16 | /* In either case, ADD their magnitudes, */ 17 | /* and use the sign of the first number. */ 18 | c->sign = sa; 19 | s_fp_add (a, b, c); 20 | } else { 21 | /* subtract a positive from a positive, OR */ 22 | /* subtract a negative from a negative. */ 23 | /* First, take the difference between their */ 24 | /* magnitudes, then... */ 25 | if (fp_cmp_mag (a, b) != FP_LT) { 26 | /* Copy the sign from the first */ 27 | c->sign = sa; 28 | /* The first has a larger or equal magnitude */ 29 | s_fp_sub (a, b, c); 30 | } else { 31 | /* The result has the *opposite* sign from */ 32 | /* the first number. */ 33 | c->sign = (sa == FP_ZPOS) ? FP_NEG : FP_ZPOS; 34 | /* The second has a larger magnitude */ 35 | s_fp_sub (b, a, c); 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/addsub/fp_sub_d.c: -------------------------------------------------------------------------------- 1 | /* TomsFastMath, a fast ISO C bignum library. -- Tom St Denis */ 2 | /* SPDX-License-Identifier: Unlicense */ 3 | #include 4 | 5 | /* c = a - b */ 6 | void fp_sub_d(const fp_int *a, fp_digit b, fp_int *c) 7 | { 8 | fp_int tmp; 9 | fp_set(&tmp, b); 10 | fp_sub(a, &tmp, c); 11 | } 12 | -------------------------------------------------------------------------------- /src/addsub/fp_submod.c: -------------------------------------------------------------------------------- 1 | /* TomsFastMath, a fast ISO C bignum library. -- Tom St Denis */ 2 | /* SPDX-License-Identifier: Unlicense */ 3 | #include 4 | 5 | /* d = a - b (mod c) */ 6 | int fp_submod(const fp_int *a, const fp_int *b, const fp_int *c, fp_int *d) 7 | { 8 | fp_int tmp; 9 | fp_zero(&tmp); 10 | fp_sub(a, b, &tmp); 11 | return fp_mod(&tmp, c, d); 12 | } 13 | -------------------------------------------------------------------------------- /src/addsub/s_fp_add.c: -------------------------------------------------------------------------------- 1 | /* TomsFastMath, a fast ISO C bignum library. -- Tom St Denis */ 2 | /* SPDX-License-Identifier: Unlicense */ 3 | #include 4 | 5 | /* unsigned addition */ 6 | void s_fp_add(const fp_int *a, const fp_int *b, fp_int *c) 7 | { 8 | int x, y, oldused; 9 | register fp_word t; 10 | 11 | y = MAX(a->used, b->used); 12 | oldused = MIN(c->used, FP_SIZE); 13 | c->used = y; 14 | 15 | t = 0; 16 | for (x = 0; x < y; x++) { 17 | t += ((fp_word)a->dp[x]) + ((fp_word)b->dp[x]); 18 | c->dp[x] = (fp_digit)t; 19 | t >>= DIGIT_BIT; 20 | } 21 | if (t != 0 && x < FP_SIZE) { 22 | c->dp[c->used++] = (fp_digit)t; 23 | ++x; 24 | } 25 | 26 | c->used = x; 27 | for (; x < oldused; x++) { 28 | c->dp[x] = 0; 29 | } 30 | fp_clamp(c); 31 | } 32 | -------------------------------------------------------------------------------- /src/addsub/s_fp_sub.c: -------------------------------------------------------------------------------- 1 | /* TomsFastMath, a fast ISO C bignum library. -- Tom St Denis */ 2 | /* SPDX-License-Identifier: Unlicense */ 3 | #include 4 | 5 | /* unsigned subtraction ||a|| >= ||b|| ALWAYS! */ 6 | void s_fp_sub(const fp_int *a, const fp_int *b, fp_int *c) 7 | { 8 | int x, oldbused, oldused; 9 | fp_word t; 10 | 11 | oldused = c->used; 12 | oldbused = b->used; 13 | c->used = a->used; 14 | t = 0; 15 | for (x = 0; x < oldbused; x++) { 16 | t = ((fp_word)a->dp[x]) - (((fp_word)b->dp[x]) + t); 17 | c->dp[x] = (fp_digit)t; 18 | t = (t >> DIGIT_BIT)&1; 19 | } 20 | for (; x < a->used; x++) { 21 | t = ((fp_word)a->dp[x]) - t; 22 | c->dp[x] = (fp_digit)t; 23 | t = (t >> DIGIT_BIT)&1; 24 | } 25 | for (; x < oldused; x++) { 26 | c->dp[x] = 0; 27 | } 28 | fp_clamp(c); 29 | } 30 | -------------------------------------------------------------------------------- /src/bin/fp_radix_size.c: -------------------------------------------------------------------------------- 1 | /* TomsFastMath, a fast ISO C bignum library. -- Tom St Denis */ 2 | /* SPDX-License-Identifier: Unlicense */ 3 | #include 4 | 5 | int fp_radix_size(const fp_int *a, int radix, int *size) 6 | { 7 | fp_int t; 8 | fp_digit d; 9 | 10 | *size = 0; 11 | 12 | /* check range of the radix */ 13 | if (radix < 2 || radix > 64) { 14 | return FP_VAL; 15 | } 16 | 17 | /* quick out if its zero */ 18 | if (fp_iszero(a) == 1) { 19 | *size = 2; 20 | return FP_OKAY; 21 | } 22 | 23 | fp_init_copy(&t, a); 24 | 25 | /* if it is negative output a - */ 26 | if (t.sign == FP_NEG) { 27 | (*size)++; 28 | t.sign = FP_ZPOS; 29 | } 30 | 31 | while (fp_iszero (&t) == FP_NO) { 32 | fp_div_d (&t, (fp_digit) radix, &t, &d); 33 | (*size)++; 34 | } 35 | 36 | /* append a NULL so the string is properly terminated */ 37 | (*size)++; 38 | return FP_OKAY; 39 | 40 | } 41 | -------------------------------------------------------------------------------- /src/bin/fp_read_radix.c: -------------------------------------------------------------------------------- 1 | /* TomsFastMath, a fast ISO C bignum library. -- Tom St Denis */ 2 | /* SPDX-License-Identifier: Unlicense */ 3 | #include 4 | 5 | int fp_read_radix(fp_int *a, const char *str, int radix) 6 | { 7 | int y, neg; 8 | char ch; 9 | 10 | /* set the integer to the default of zero */ 11 | fp_zero (a); 12 | 13 | /* make sure the radix is ok */ 14 | if (radix < 2 || radix > 64) { 15 | return FP_VAL; 16 | } 17 | 18 | /* if the leading digit is a 19 | * minus set the sign to negative. 20 | */ 21 | if (*str == '-') { 22 | ++str; 23 | neg = FP_NEG; 24 | } else { 25 | neg = FP_ZPOS; 26 | } 27 | 28 | /* process each digit of the string */ 29 | while (*str) { 30 | /* if the radix < 36 the conversion is case insensitive 31 | * this allows numbers like 1AB and 1ab to represent the same value 32 | * [e.g. in hex] 33 | */ 34 | ch = (char) ((radix <= 36) ? toupper ((int)*str) : *str); 35 | for (y = 0; y < 64; y++) { 36 | if (ch == fp_s_rmap[y]) { 37 | break; 38 | } 39 | } 40 | 41 | /* if the char was found in the map 42 | * and is less than the given radix add it 43 | * to the number, otherwise exit the loop. 44 | */ 45 | if (y < radix) { 46 | fp_mul_d (a, (fp_digit) radix, a); 47 | fp_add_d (a, (fp_digit) y, a); 48 | } else { 49 | break; 50 | } 51 | ++str; 52 | } 53 | 54 | /* set the sign only if a != 0 */ 55 | if (fp_iszero(a) != FP_YES) { 56 | a->sign = neg; 57 | } 58 | return FP_OKAY; 59 | } 60 | -------------------------------------------------------------------------------- /src/bin/fp_read_signed_bin.c: -------------------------------------------------------------------------------- 1 | /* TomsFastMath, a fast ISO C bignum library. -- Tom St Denis */ 2 | /* SPDX-License-Identifier: Unlicense */ 3 | #include 4 | 5 | void fp_read_signed_bin(fp_int *a, const unsigned char *b, int c) 6 | { 7 | /* read magnitude */ 8 | fp_read_unsigned_bin (a, b + 1, c - 1); 9 | 10 | /* first byte is 0 for positive, non-zero for negative */ 11 | if (b[0] == 0) { 12 | a->sign = FP_ZPOS; 13 | } else { 14 | a->sign = FP_NEG; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/bin/fp_read_unsigned_bin.c: -------------------------------------------------------------------------------- 1 | /* TomsFastMath, a fast ISO C bignum library. -- Tom St Denis */ 2 | /* SPDX-License-Identifier: Unlicense */ 3 | #include 4 | 5 | void fp_read_unsigned_bin(fp_int *a, const unsigned char *b, int c) 6 | { 7 | /* zero the int */ 8 | fp_zero (a); 9 | 10 | if ((unsigned)c > (FP_SIZE * sizeof(fp_digit))) { 11 | int excess = c - (FP_SIZE * sizeof(fp_digit)); 12 | c -= excess; 13 | b += excess; 14 | } 15 | 16 | /* If we know the endianness of this architecture, and we're using 17 | 32-bit fp_digits, we can optimize this */ 18 | #if (defined(ENDIAN_LITTLE) || defined(ENDIAN_BIG)) && !defined(FP_64BIT) 19 | /* But not for both simultaneously */ 20 | #if defined(ENDIAN_LITTLE) && defined(ENDIAN_BIG) 21 | #error Both ENDIAN_LITTLE and ENDIAN_BIG defined. 22 | #endif 23 | { 24 | unsigned char *pd = (unsigned char *)a->dp; 25 | 26 | a->used = (c + sizeof(fp_digit) - 1)/sizeof(fp_digit); 27 | /* read the bytes in */ 28 | #ifdef ENDIAN_BIG 29 | { 30 | /* Use Duff's device to unroll the loop. */ 31 | int idx = (c - 1) & ~3; 32 | switch (c % 4) { 33 | case 0: do { pd[idx+0] = *b++; 34 | case 3: pd[idx+1] = *b++; 35 | case 2: pd[idx+2] = *b++; 36 | case 1: pd[idx+3] = *b++; 37 | idx -= 4; 38 | } while ((c -= 4) > 0); 39 | } 40 | } 41 | #else 42 | for (c -= 1; c >= 0; c -= 1) { 43 | pd[c] = *b++; 44 | } 45 | #endif 46 | } 47 | #else 48 | /* read the bytes in */ 49 | for (; c > 0; c--) { 50 | fp_mul_2d (a, 8, a); 51 | a->dp[0] |= *b++; 52 | 53 | if (a->used == 0) { 54 | a->used = 1; 55 | } 56 | } 57 | #endif 58 | fp_clamp (a); 59 | } 60 | -------------------------------------------------------------------------------- /src/bin/fp_reverse.c: -------------------------------------------------------------------------------- 1 | /* TomsFastMath, a fast ISO C bignum library. -- Tom St Denis */ 2 | /* SPDX-License-Identifier: Unlicense */ 3 | #include 4 | 5 | /* reverse an array, used for radix code */ 6 | void fp_reverse (unsigned char *s, int len) 7 | { 8 | int ix, iy; 9 | unsigned char t; 10 | 11 | ix = 0; 12 | iy = len - 1; 13 | while (ix < iy) { 14 | t = s[ix]; 15 | s[ix] = s[iy]; 16 | s[iy] = t; 17 | ++ix; 18 | --iy; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/bin/fp_s_rmap.c: -------------------------------------------------------------------------------- 1 | /* TomsFastMath, a fast ISO C bignum library. -- Tom St Denis */ 2 | /* SPDX-License-Identifier: Unlicense */ 3 | #include 4 | 5 | /* chars used in radix conversions */ 6 | const char *fp_s_rmap = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz+/"; 7 | -------------------------------------------------------------------------------- /src/bin/fp_signed_bin_size.c: -------------------------------------------------------------------------------- 1 | /* TomsFastMath, a fast ISO C bignum library. -- Tom St Denis */ 2 | /* SPDX-License-Identifier: Unlicense */ 3 | #include 4 | 5 | int fp_signed_bin_size(const fp_int *a) 6 | { 7 | return 1 + fp_unsigned_bin_size (a); 8 | } 9 | -------------------------------------------------------------------------------- /src/bin/fp_to_signed_bin.c: -------------------------------------------------------------------------------- 1 | /* TomsFastMath, a fast ISO C bignum library. -- Tom St Denis */ 2 | /* SPDX-License-Identifier: Unlicense */ 3 | #include 4 | 5 | void fp_to_signed_bin(const fp_int *a, unsigned char *b) 6 | { 7 | fp_to_unsigned_bin (a, b + 1); 8 | b[0] = (unsigned char) ((a->sign == FP_ZPOS) ? 0 : 1); 9 | } 10 | -------------------------------------------------------------------------------- /src/bin/fp_to_unsigned_bin.c: -------------------------------------------------------------------------------- 1 | /* TomsFastMath, a fast ISO C bignum library. -- Tom St Denis */ 2 | /* SPDX-License-Identifier: Unlicense */ 3 | #include 4 | 5 | void fp_to_unsigned_bin(const fp_int *a, unsigned char *b) 6 | { 7 | int x; 8 | fp_int t; 9 | 10 | fp_init_copy(&t, a); 11 | 12 | x = 0; 13 | while (fp_iszero (&t) == FP_NO) { 14 | b[x++] = (unsigned char) (t.dp[0] & 255); 15 | fp_div_2d (&t, 8, &t, NULL); 16 | } 17 | fp_reverse (b, x); 18 | } 19 | -------------------------------------------------------------------------------- /src/bin/fp_toradix.c: -------------------------------------------------------------------------------- 1 | /* TomsFastMath, a fast ISO C bignum library. -- Tom St Denis */ 2 | /* SPDX-License-Identifier: Unlicense */ 3 | #include 4 | 5 | /** 6 | * a: pointer to fp_int representing the input number 7 | * str: output buffer 8 | * radix: number of character to use for encoding of the number 9 | * 10 | * The radix value can be in the range 2 to 64. This function converts number 11 | * a into a string str. Please don't use this function because a too small 12 | * chosen str buffer would lead to an overflow which can not be detected. 13 | * Please use fp_toradix_n() instead. 14 | * 15 | * Return: FP_VAL on error, FP_OKAY on success. 16 | */ 17 | int fp_toradix(const fp_int *a, char *str, int radix) 18 | { 19 | return fp_toradix_n(a, str, radix, INT_MAX); 20 | } 21 | -------------------------------------------------------------------------------- /src/bin/fp_toradix_n.c: -------------------------------------------------------------------------------- 1 | /* TomsFastMath, a fast ISO C bignum library. -- Tom St Denis */ 2 | /* SPDX-License-Identifier: Unlicense */ 3 | #include 4 | 5 | int fp_toradix_n(const fp_int *a, char *str, int radix, int maxlen) 6 | { 7 | int digs; 8 | fp_int t; 9 | fp_digit d = 0; 10 | char *_s = str; 11 | 12 | /* check range of the radix */ 13 | if (maxlen < 2 || radix < 2 || radix > 64) 14 | return FP_VAL; 15 | 16 | /* quick check for zero */ 17 | if (fp_iszero(a) == FP_YES) { 18 | *str++ = '0'; 19 | *str = '\0'; 20 | return FP_OKAY; 21 | } 22 | 23 | fp_init_copy(&t, a); 24 | 25 | /* if it is negative output a - */ 26 | if (t.sign == FP_NEG) { 27 | /* we have to reverse our digits later... but not the - sign!! */ 28 | ++_s; 29 | 30 | /* store the flag and mark the number as positive */ 31 | *str++ = '-'; 32 | t.sign = FP_ZPOS; 33 | 34 | /* subtract a char */ 35 | --maxlen; 36 | } 37 | 38 | digs = 0; 39 | while (fp_iszero (&t) == FP_NO) { 40 | if (--maxlen < 1) { 41 | /* no more room */ 42 | break; 43 | } 44 | fp_div_d(&t, (fp_digit) radix, &t, &d); 45 | *str++ = fp_s_rmap[d]; 46 | ++digs; 47 | } 48 | 49 | /* reverse the digits of the string. In this case _s points 50 | * to the first digit [exluding the sign] of the number] 51 | */ 52 | fp_reverse((unsigned char *) _s, digs); 53 | 54 | /* append a NULL so the string is properly terminated */ 55 | *str = '\0'; 56 | 57 | if (maxlen < 1) 58 | return FP_VAL; 59 | return FP_OKAY; 60 | } 61 | -------------------------------------------------------------------------------- /src/bin/fp_unsigned_bin_size.c: -------------------------------------------------------------------------------- 1 | /* TomsFastMath, a fast ISO C bignum library. -- Tom St Denis */ 2 | /* SPDX-License-Identifier: Unlicense */ 3 | #include 4 | 5 | int fp_unsigned_bin_size(const fp_int *a) 6 | { 7 | int size = fp_count_bits (a); 8 | return (size / 8 + ((size & 7) != 0 ? 1 : 0)); 9 | } 10 | -------------------------------------------------------------------------------- /src/bit/fp_cnt_lsb.c: -------------------------------------------------------------------------------- 1 | /* TomsFastMath, a fast ISO C bignum library. -- Tom St Denis */ 2 | /* SPDX-License-Identifier: Unlicense */ 3 | #include 4 | 5 | static const int lnz[16] = { 6 | 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0 7 | }; 8 | 9 | /* Counts the number of lsbs which are zero before the first zero bit */ 10 | int fp_cnt_lsb(const fp_int *a) 11 | { 12 | int x; 13 | fp_digit q, qq; 14 | 15 | /* easy out */ 16 | if (fp_iszero(a) == 1) { 17 | return 0; 18 | } 19 | 20 | /* scan lower digits until non-zero */ 21 | for (x = 0; x < a->used && a->dp[x] == 0; x++); 22 | q = a->dp[x]; 23 | x *= DIGIT_BIT; 24 | 25 | /* now scan this digit until a 1 is found */ 26 | if ((q & 1) == 0) { 27 | do { 28 | qq = q & 15; 29 | x += lnz[qq]; 30 | q >>= 4; 31 | } while (qq == 0); 32 | } 33 | return x; 34 | } 35 | -------------------------------------------------------------------------------- /src/bit/fp_count_bits.c: -------------------------------------------------------------------------------- 1 | /* TomsFastMath, a fast ISO C bignum library. -- Tom St Denis */ 2 | /* SPDX-License-Identifier: Unlicense */ 3 | #include 4 | 5 | int fp_count_bits (const fp_int * a) 6 | { 7 | int r; 8 | fp_digit q; 9 | 10 | /* shortcut */ 11 | if (a->used == 0) { 12 | return 0; 13 | } 14 | 15 | /* get number of digits and add that */ 16 | r = (a->used - 1) * DIGIT_BIT; 17 | 18 | /* take the last digit and count the bits in it */ 19 | q = a->dp[a->used - 1]; 20 | while (q > ((fp_digit) 0)) { 21 | ++r; 22 | q >>= ((fp_digit) 1); 23 | } 24 | return r; 25 | } 26 | -------------------------------------------------------------------------------- /src/bit/fp_div_2.c: -------------------------------------------------------------------------------- 1 | /* TomsFastMath, a fast ISO C bignum library. -- Tom St Denis */ 2 | /* SPDX-License-Identifier: Unlicense */ 3 | #include 4 | 5 | /* b = a/2 */ 6 | void fp_div_2(const fp_int * a, fp_int * b) 7 | { 8 | int x, oldused; 9 | 10 | oldused = b->used; 11 | b->used = a->used; 12 | { 13 | register const fp_digit *tmpa; 14 | register fp_digit r, rr, *tmpb; 15 | 16 | /* source alias */ 17 | tmpa = a->dp + b->used - 1; 18 | 19 | /* dest alias */ 20 | tmpb = b->dp + b->used - 1; 21 | 22 | /* carry */ 23 | r = 0; 24 | for (x = b->used - 1; x >= 0; x--) { 25 | /* get the carry for the next iteration */ 26 | rr = *tmpa & 1; 27 | 28 | /* shift the current digit, add in carry and store */ 29 | *tmpb-- = (*tmpa-- >> 1) | (r << (DIGIT_BIT - 1)); 30 | 31 | /* forward carry to next iteration */ 32 | r = rr; 33 | } 34 | 35 | /* zero excess digits */ 36 | tmpb = b->dp + b->used; 37 | for (x = b->used; x < oldused; x++) { 38 | *tmpb++ = 0; 39 | } 40 | } 41 | b->sign = a->sign; 42 | fp_clamp (b); 43 | } 44 | -------------------------------------------------------------------------------- /src/bit/fp_div_2d.c: -------------------------------------------------------------------------------- 1 | /* TomsFastMath, a fast ISO C bignum library. -- Tom St Denis */ 2 | /* SPDX-License-Identifier: Unlicense */ 3 | #include 4 | 5 | /* c = a / 2**b */ 6 | void fp_div_2d(const fp_int *a, int b, fp_int *c, fp_int *d) 7 | { 8 | fp_digit D, r, rr; 9 | int x; 10 | fp_int t; 11 | 12 | /* if the shift count is <= 0 then we do no work */ 13 | if (b <= 0) { 14 | fp_copy (a, c); 15 | if (d != NULL) { 16 | fp_zero (d); 17 | } 18 | return; 19 | } 20 | 21 | fp_init(&t); 22 | 23 | /* get the remainder */ 24 | if (d != NULL) { 25 | fp_mod_2d (a, b, &t); 26 | } 27 | 28 | /* copy */ 29 | fp_copy(a, c); 30 | 31 | /* shift by as many digits in the bit count */ 32 | if (b >= (int)DIGIT_BIT) { 33 | fp_rshd (c, b / DIGIT_BIT); 34 | } 35 | 36 | /* shift any bit count < DIGIT_BIT */ 37 | D = (fp_digit) (b % DIGIT_BIT); 38 | if (D != 0) { 39 | register fp_digit *tmpc, mask, shift; 40 | 41 | /* mask */ 42 | mask = (((fp_digit)1) << D) - 1; 43 | 44 | /* shift for lsb */ 45 | shift = DIGIT_BIT - D; 46 | 47 | /* alias */ 48 | tmpc = c->dp + (c->used - 1); 49 | 50 | /* carry */ 51 | r = 0; 52 | for (x = c->used - 1; x >= 0; x--) { 53 | /* get the lower bits of this word in a temp */ 54 | rr = *tmpc & mask; 55 | 56 | /* shift the current word and mix in the carry bits from the previous word */ 57 | *tmpc = (*tmpc >> D) | (r << shift); 58 | --tmpc; 59 | 60 | /* set the carry to the carry bits of the current word found above */ 61 | r = rr; 62 | } 63 | } 64 | fp_clamp (c); 65 | if (d != NULL) { 66 | fp_copy (&t, d); 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/bit/fp_lshd.c: -------------------------------------------------------------------------------- 1 | /* TomsFastMath, a fast ISO C bignum library. -- Tom St Denis */ 2 | /* SPDX-License-Identifier: Unlicense */ 3 | #include 4 | 5 | void fp_lshd(fp_int *a, int x) 6 | { 7 | int y; 8 | 9 | /* move up and truncate as required */ 10 | y = MIN(a->used + x - 1, (int)(FP_SIZE-1)); 11 | 12 | /* store new size */ 13 | a->used = y + 1; 14 | 15 | /* move digits */ 16 | for (; y >= x; y--) { 17 | a->dp[y] = a->dp[y-x]; 18 | } 19 | 20 | /* zero lower digits */ 21 | for (; y >= 0; y--) { 22 | a->dp[y] = 0; 23 | } 24 | 25 | /* clamp digits */ 26 | fp_clamp(a); 27 | } 28 | -------------------------------------------------------------------------------- /src/bit/fp_mod_2d.c: -------------------------------------------------------------------------------- 1 | /* TomsFastMath, a fast ISO C bignum library. -- Tom St Denis */ 2 | /* SPDX-License-Identifier: Unlicense */ 3 | #include 4 | 5 | /* c = a mod 2**d */ 6 | void fp_mod_2d(const fp_int *a, int b, fp_int *c) 7 | { 8 | int x; 9 | 10 | /* zero if count less than or equal to zero */ 11 | if (b <= 0) { 12 | fp_zero(c); 13 | return; 14 | } 15 | 16 | /* get copy of input */ 17 | fp_copy(a, c); 18 | 19 | /* if 2**d is larger than we just return */ 20 | if (b >= (DIGIT_BIT * a->used)) { 21 | return; 22 | } 23 | 24 | /* zero digits above the last digit of the modulus */ 25 | for (x = (b / DIGIT_BIT) + ((b % DIGIT_BIT) == 0 ? 0 : 1); x < c->used; x++) { 26 | c->dp[x] = 0; 27 | } 28 | /* clear the digit that is not completely outside/inside the modulus */ 29 | c->dp[b / DIGIT_BIT] &= ~((fp_digit)0) >> (DIGIT_BIT - b); 30 | fp_clamp (c); 31 | } 32 | -------------------------------------------------------------------------------- /src/bit/fp_rshd.c: -------------------------------------------------------------------------------- 1 | /* TomsFastMath, a fast ISO C bignum library. -- Tom St Denis */ 2 | /* SPDX-License-Identifier: Unlicense */ 3 | #include 4 | 5 | void fp_rshd(fp_int *a, int x) 6 | { 7 | int y; 8 | 9 | /* too many digits just zero and return */ 10 | if (x >= a->used) { 11 | fp_zero(a); 12 | return; 13 | } 14 | 15 | /* shift */ 16 | for (y = 0; y < a->used - x; y++) { 17 | a->dp[y] = a->dp[y+x]; 18 | } 19 | 20 | /* zero rest */ 21 | for (; y < a->used; y++) { 22 | a->dp[y] = 0; 23 | } 24 | 25 | /* decrement count */ 26 | a->used -= x; 27 | fp_clamp(a); 28 | } 29 | -------------------------------------------------------------------------------- /src/divide/fp_div.c: -------------------------------------------------------------------------------- 1 | /* TomsFastMath, a fast ISO C bignum library. -- Tom St Denis */ 2 | /* SPDX-License-Identifier: Unlicense */ 3 | #include 4 | 5 | /* a/b => cb + d == a */ 6 | int fp_div(const fp_int *a, const fp_int *b, fp_int *c, fp_int *d) 7 | { 8 | fp_int q, x, y, t1, t2; 9 | int n, t, i, norm, neg; 10 | 11 | /* is divisor zero ? */ 12 | if (fp_iszero (b) == 1) { 13 | return FP_VAL; 14 | } 15 | 16 | /* if a < b then q=0, r = a */ 17 | if (fp_cmp_mag (a, b) == FP_LT) { 18 | if (d != NULL) { 19 | fp_copy (a, d); 20 | } 21 | if (c != NULL) { 22 | fp_zero (c); 23 | } 24 | return FP_OKAY; 25 | } 26 | 27 | fp_init(&q); 28 | q.used = a->used + 2; 29 | 30 | fp_init(&t1); 31 | fp_init(&t2); 32 | fp_init_copy(&x, a); 33 | fp_init_copy(&y, b); 34 | 35 | /* fix the sign */ 36 | neg = (a->sign == b->sign) ? FP_ZPOS : FP_NEG; 37 | x.sign = y.sign = FP_ZPOS; 38 | 39 | /* normalize both x and y, ensure that y >= b/2, [b == 2**DIGIT_BIT] */ 40 | norm = fp_count_bits(&y) % DIGIT_BIT; 41 | if (norm < (int)(DIGIT_BIT-1)) { 42 | norm = (DIGIT_BIT-1) - norm; 43 | fp_mul_2d (&x, norm, &x); 44 | fp_mul_2d (&y, norm, &y); 45 | } else { 46 | norm = 0; 47 | } 48 | 49 | /* note hac does 0 based, so if used==5 then its 0,1,2,3,4, e.g. use 4 */ 50 | n = x.used - 1; 51 | t = y.used - 1; 52 | 53 | /* while (x >= y*b**n-t) do { q[n-t] += 1; x -= y*b**{n-t} } */ 54 | fp_lshd (&y, n - t); /* y = y*b**{n-t} */ 55 | 56 | while (fp_cmp (&x, &y) != FP_LT) { 57 | ++(q.dp[n - t]); 58 | fp_sub (&x, &y, &x); 59 | } 60 | 61 | /* reset y by shifting it back down */ 62 | fp_rshd (&y, n - t); 63 | 64 | /* step 3. for i from n down to (t + 1) */ 65 | for (i = n; i >= (t + 1); i--) { 66 | if (i > x.used) { 67 | continue; 68 | } 69 | 70 | /* step 3.1 if xi == yt then set q{i-t-1} to b-1, 71 | * otherwise set q{i-t-1} to (xi*b + x{i-1})/yt */ 72 | if (x.dp[i] == y.dp[t]) { 73 | q.dp[i - t - 1] = ((((fp_word)1) << DIGIT_BIT) - 1); 74 | } else { 75 | fp_word tmp; 76 | tmp = ((fp_word) x.dp[i]) << ((fp_word) DIGIT_BIT); 77 | tmp |= ((fp_word) x.dp[i - 1]); 78 | tmp /= ((fp_word) y.dp[t]); 79 | q.dp[i - t - 1] = (fp_digit) (tmp); 80 | } 81 | 82 | /* while (q{i-t-1} * (yt * b + y{t-1})) > 83 | xi * b**2 + xi-1 * b + xi-2 84 | 85 | do q{i-t-1} -= 1; 86 | */ 87 | q.dp[i - t - 1] = (q.dp[i - t - 1] + 1); 88 | do { 89 | q.dp[i - t - 1] = (q.dp[i - t - 1] - 1); 90 | 91 | /* find left hand */ 92 | fp_zero (&t1); 93 | t1.dp[0] = (t - 1 < 0) ? 0 : y.dp[t - 1]; 94 | t1.dp[1] = y.dp[t]; 95 | t1.used = 2; 96 | fp_mul_d (&t1, q.dp[i - t - 1], &t1); 97 | 98 | /* find right hand */ 99 | t2.dp[0] = (i - 2 < 0) ? 0 : x.dp[i - 2]; 100 | t2.dp[1] = (i - 1 < 0) ? 0 : x.dp[i - 1]; 101 | t2.dp[2] = x.dp[i]; 102 | t2.used = 3; 103 | } while (fp_cmp_mag(&t1, &t2) == FP_GT); 104 | 105 | /* step 3.3 x = x - q{i-t-1} * y * b**{i-t-1} */ 106 | fp_mul_d (&y, q.dp[i - t - 1], &t1); 107 | fp_lshd (&t1, i - t - 1); 108 | fp_sub (&x, &t1, &x); 109 | 110 | /* if x < 0 then { x = x + y*b**{i-t-1}; q{i-t-1} -= 1; } */ 111 | if (x.sign == FP_NEG) { 112 | fp_copy (&y, &t1); 113 | fp_lshd (&t1, i - t - 1); 114 | fp_add (&x, &t1, &x); 115 | q.dp[i - t - 1] = q.dp[i - t - 1] - 1; 116 | } 117 | } 118 | 119 | /* now q is the quotient and x is the remainder 120 | * [which we have to normalize] 121 | */ 122 | 123 | /* get sign before writing to c */ 124 | x.sign = x.used == 0 ? FP_ZPOS : a->sign; 125 | 126 | if (c != NULL) { 127 | fp_clamp (&q); 128 | fp_copy (&q, c); 129 | c->sign = neg; 130 | } 131 | 132 | if (d != NULL) { 133 | fp_div_2d (&x, norm, &x, NULL); 134 | 135 | /* the following is a kludge, essentially we were seeing the right remainder but 136 | with excess digits that should have been zero 137 | */ 138 | for (i = b->used; i < x.used; i++) { 139 | x.dp[i] = 0; 140 | } 141 | fp_clamp(&x); 142 | fp_copy (&x, d); 143 | } 144 | 145 | return FP_OKAY; 146 | } 147 | -------------------------------------------------------------------------------- /src/divide/fp_div_d.c: -------------------------------------------------------------------------------- 1 | /* TomsFastMath, a fast ISO C bignum library. -- Tom St Denis */ 2 | /* SPDX-License-Identifier: Unlicense */ 3 | #include 4 | 5 | static int s_is_power_of_two(fp_digit b, int *p) 6 | { 7 | int x; 8 | 9 | /* fast return if no power of two */ 10 | if ((b==0) || (b & (b-1))) { 11 | return 0; 12 | } 13 | 14 | for (x = 0; x < DIGIT_BIT; x++) { 15 | if (b == (((fp_digit)1)< cb + d == a */ 24 | int fp_div_d(const fp_int *a, fp_digit b, fp_int *c, fp_digit *d) 25 | { 26 | fp_int q; 27 | fp_word w; 28 | fp_digit t; 29 | int ix; 30 | 31 | /* cannot divide by zero */ 32 | if (b == 0) { 33 | return FP_VAL; 34 | } 35 | 36 | /* quick outs */ 37 | if (b == 1 || fp_iszero(a) == 1) { 38 | if (d != NULL) { 39 | *d = 0; 40 | } 41 | if (c != NULL) { 42 | fp_copy(a, c); 43 | } 44 | return FP_OKAY; 45 | } 46 | 47 | /* power of two ? */ 48 | if (s_is_power_of_two(b, &ix) == 1) { 49 | if (d != NULL) { 50 | *d = a->dp[0] & ((((fp_digit)1)<used; 62 | q.sign = a->sign; 63 | w = 0; 64 | for (ix = a->used - 1; ix >= 0; ix--) { 65 | w = (w << ((fp_word)DIGIT_BIT)) | ((fp_word)a->dp[ix]); 66 | 67 | if (w >= b) { 68 | t = (fp_digit)(w / b); 69 | w -= ((fp_word)t) * ((fp_word)b); 70 | } else { 71 | t = 0; 72 | } 73 | q.dp[ix] = (fp_digit)t; 74 | } 75 | 76 | if (d != NULL) { 77 | *d = (fp_digit)w; 78 | } 79 | 80 | if (c != NULL) { 81 | fp_clamp(&q); 82 | fp_copy(&q, c); 83 | } 84 | 85 | return FP_OKAY; 86 | } 87 | -------------------------------------------------------------------------------- /src/divide/fp_mod.c: -------------------------------------------------------------------------------- 1 | /* TomsFastMath, a fast ISO C bignum library. -- Tom St Denis */ 2 | /* SPDX-License-Identifier: Unlicense */ 3 | #include 4 | 5 | /* c = a mod b, 0 <= c < b */ 6 | int fp_mod(const fp_int *a, const fp_int *b, fp_int *c) 7 | { 8 | fp_int t; 9 | int err; 10 | 11 | fp_zero(&t); 12 | if ((err = fp_div(a, b, NULL, &t)) != FP_OKAY) { 13 | return err; 14 | } 15 | if (t.sign != b->sign) { 16 | fp_add(&t, b, c); 17 | } else { 18 | fp_copy(&t, c); 19 | } 20 | return FP_OKAY; 21 | } 22 | -------------------------------------------------------------------------------- /src/divide/fp_mod_d.c: -------------------------------------------------------------------------------- 1 | /* TomsFastMath, a fast ISO C bignum library. -- Tom St Denis */ 2 | /* SPDX-License-Identifier: Unlicense */ 3 | #include 4 | 5 | /* c = a mod b, 0 <= c < b */ 6 | int fp_mod_d(const fp_int *a, fp_digit b, fp_digit *c) 7 | { 8 | return fp_div_d(a, b, NULL, c); 9 | } 10 | -------------------------------------------------------------------------------- /src/exptmod/fp_2expt.c: -------------------------------------------------------------------------------- 1 | /* TomsFastMath, a fast ISO C bignum library. -- Tom St Denis */ 2 | /* SPDX-License-Identifier: Unlicense */ 3 | #include 4 | 5 | /* computes a = 2**b */ 6 | void fp_2expt(fp_int *a, int b) 7 | { 8 | int z; 9 | 10 | /* zero a as per default */ 11 | fp_zero (a); 12 | 13 | if (b < 0) { 14 | return; 15 | } 16 | 17 | z = b / DIGIT_BIT; 18 | if (z >= FP_SIZE) { 19 | return; 20 | } 21 | 22 | /* set the used count of where the bit will go */ 23 | a->used = z + 1; 24 | 25 | /* put the single bit in its place */ 26 | a->dp[z] = ((fp_digit)1) << (b % DIGIT_BIT); 27 | } 28 | -------------------------------------------------------------------------------- /src/exptmod/fp_exptmod.c: -------------------------------------------------------------------------------- 1 | /* TomsFastMath, a fast ISO C bignum library. -- Tom St Denis */ 2 | /* SPDX-License-Identifier: Unlicense */ 3 | #include 4 | 5 | #ifdef TFM_TIMING_RESISTANT 6 | 7 | /* timing resistant montgomery ladder based exptmod 8 | 9 | Based on work by Marc Joye, Sung-Ming Yen, "The Montgomery Powering Ladder", Cryptographic Hardware and Embedded Systems, CHES 2002 10 | */ 11 | static int s_fp_exptmod(fp_int * G, const fp_int * X, const fp_int * P, fp_int * Y) 12 | { 13 | fp_int R[2]; 14 | fp_digit buf, mp; 15 | int err, bitcnt, digidx, y; 16 | 17 | /* now setup montgomery */ 18 | if ((err = fp_montgomery_setup (P, &mp)) != FP_OKAY) { 19 | return err; 20 | } 21 | 22 | fp_init(&R[0]); 23 | fp_init(&R[1]); 24 | 25 | /* now we need R mod m */ 26 | fp_montgomery_calc_normalization (&R[0], P); 27 | 28 | /* now set R[0][1] to G * R mod m */ 29 | if (fp_cmp_mag(P, G) != FP_GT) { 30 | /* G > P so we reduce it first */ 31 | fp_mod(G, P, &R[1]); 32 | } else { 33 | fp_copy(G, &R[1]); 34 | } 35 | fp_mulmod (&R[1], &R[0], P, &R[1]); 36 | 37 | /* for j = t-1 downto 0 do 38 | r_!k = R0*R1; r_k = r_k^2 39 | */ 40 | 41 | /* set initial mode and bit cnt */ 42 | bitcnt = 1; 43 | buf = 0; 44 | digidx = X->used - 1; 45 | 46 | for (;;) { 47 | /* grab next digit as required */ 48 | if (--bitcnt == 0) { 49 | /* if digidx == -1 we are out of digits so break */ 50 | if (digidx == -1) { 51 | break; 52 | } 53 | /* read next digit and reset bitcnt */ 54 | buf = X->dp[digidx--]; 55 | bitcnt = (int)DIGIT_BIT; 56 | } 57 | 58 | /* grab the next msb from the exponent */ 59 | y = (fp_digit)(buf >> (DIGIT_BIT - 1)) & 1; 60 | buf <<= (fp_digit)1; 61 | 62 | /* do ops */ 63 | fp_mul(&R[0], &R[1], &R[y^1]); fp_montgomery_reduce(&R[y^1], P, mp); 64 | fp_sqr(&R[y], &R[y]); fp_montgomery_reduce(&R[y], P, mp); 65 | } 66 | 67 | fp_montgomery_reduce(&R[0], P, mp); 68 | fp_copy(&R[0], Y); 69 | return FP_OKAY; 70 | } 71 | 72 | #else 73 | 74 | /* y = g**x (mod b) 75 | * Some restrictions... x must be positive and < b 76 | */ 77 | static int s_fp_exptmod(const fp_int * G, const fp_int * X, const fp_int * P, fp_int * Y) 78 | { 79 | fp_int M[64], res; 80 | fp_digit buf, mp; 81 | int err, bitbuf, bitcpy, bitcnt, mode, digidx, x, y, winsize; 82 | 83 | /* find window size */ 84 | x = fp_count_bits (X); 85 | if (x <= 21) { 86 | winsize = 1; 87 | } else if (x <= 36) { 88 | winsize = 3; 89 | } else if (x <= 140) { 90 | winsize = 4; 91 | } else if (x <= 450) { 92 | winsize = 5; 93 | } else { 94 | winsize = 6; 95 | } 96 | 97 | /* init M array */ 98 | memset(M, 0, sizeof(M)); 99 | 100 | /* now setup montgomery */ 101 | if ((err = fp_montgomery_setup (P, &mp)) != FP_OKAY) { 102 | return err; 103 | } 104 | 105 | /* setup result */ 106 | fp_init(&res); 107 | 108 | /* create M table 109 | * 110 | * The M table contains powers of the input base, e.g. M[x] = G^x mod P 111 | * 112 | * The first half of the table is not computed though accept for M[0] and M[1] 113 | */ 114 | 115 | /* now we need R mod m */ 116 | fp_montgomery_calc_normalization (&res, P); 117 | 118 | /* now set M[1] to G * R mod m */ 119 | if (fp_cmp_mag(P, G) != FP_GT) { 120 | /* G > P so we reduce it first */ 121 | fp_mod(G, P, &M[1]); 122 | } else { 123 | fp_copy(G, &M[1]); 124 | } 125 | fp_mulmod (&M[1], &res, P, &M[1]); 126 | 127 | /* compute the value at M[1<<(winsize-1)] by squaring M[1] (winsize-1) times */ 128 | fp_copy (&M[1], &M[1 << (winsize - 1)]); 129 | for (x = 0; x < (winsize - 1); x++) { 130 | fp_sqr (&M[1 << (winsize - 1)], &M[1 << (winsize - 1)]); 131 | fp_montgomery_reduce (&M[1 << (winsize - 1)], P, mp); 132 | } 133 | 134 | /* create upper table */ 135 | for (x = (1 << (winsize - 1)) + 1; x < (1 << winsize); x++) { 136 | fp_mul(&M[x - 1], &M[1], &M[x]); 137 | fp_montgomery_reduce(&M[x], P, mp); 138 | } 139 | 140 | /* set initial mode and bit cnt */ 141 | mode = 0; 142 | bitcnt = 1; 143 | buf = 0; 144 | digidx = X->used - 1; 145 | bitcpy = 0; 146 | bitbuf = 0; 147 | 148 | for (;;) { 149 | /* grab next digit as required */ 150 | if (--bitcnt == 0) { 151 | /* if digidx == -1 we are out of digits so break */ 152 | if (digidx == -1) { 153 | break; 154 | } 155 | /* read next digit and reset bitcnt */ 156 | buf = X->dp[digidx--]; 157 | bitcnt = (int)DIGIT_BIT; 158 | } 159 | 160 | /* grab the next msb from the exponent */ 161 | y = (fp_digit)(buf >> (DIGIT_BIT - 1)) & 1; 162 | buf <<= (fp_digit)1; 163 | 164 | /* if the bit is zero and mode == 0 then we ignore it 165 | * These represent the leading zero bits before the first 1 bit 166 | * in the exponent. Technically this opt is not required but it 167 | * does lower the # of trivial squaring/reductions used 168 | */ 169 | if (mode == 0 && y == 0) { 170 | continue; 171 | } 172 | 173 | /* if the bit is zero and mode == 1 then we square */ 174 | if (mode == 1 && y == 0) { 175 | fp_sqr(&res, &res); 176 | fp_montgomery_reduce(&res, P, mp); 177 | continue; 178 | } 179 | 180 | /* else we add it to the window */ 181 | bitbuf |= (y << (winsize - ++bitcpy)); 182 | mode = 2; 183 | 184 | if (bitcpy == winsize) { 185 | /* ok window is filled so square as required and multiply */ 186 | /* square first */ 187 | for (x = 0; x < winsize; x++) { 188 | fp_sqr(&res, &res); 189 | fp_montgomery_reduce(&res, P, mp); 190 | } 191 | 192 | /* then multiply */ 193 | fp_mul(&res, &M[bitbuf], &res); 194 | fp_montgomery_reduce(&res, P, mp); 195 | 196 | /* empty window and reset */ 197 | bitcpy = 0; 198 | bitbuf = 0; 199 | mode = 1; 200 | } 201 | } 202 | 203 | /* if bits remain then square/multiply */ 204 | if (mode == 2 && bitcpy > 0) { 205 | /* square then multiply if the bit is set */ 206 | for (x = 0; x < bitcpy; x++) { 207 | fp_sqr(&res, &res); 208 | fp_montgomery_reduce(&res, P, mp); 209 | 210 | /* get next bit of the window */ 211 | bitbuf <<= 1; 212 | if ((bitbuf & (1 << winsize)) != 0) { 213 | /* then multiply */ 214 | fp_mul(&res, &M[1], &res); 215 | fp_montgomery_reduce(&res, P, mp); 216 | } 217 | } 218 | } 219 | 220 | /* fixup result if Montgomery reduction is used 221 | * recall that any value in a Montgomery system is 222 | * actually multiplied by R mod n. So we have 223 | * to reduce one more time to cancel out the factor 224 | * of R. 225 | */ 226 | fp_montgomery_reduce(&res, P, mp); 227 | 228 | /* swap res with Y */ 229 | fp_copy (&res, Y); 230 | return FP_OKAY; 231 | } 232 | 233 | #endif 234 | 235 | /* 236 | * X should really be const... however, if it's negative, this function 237 | * temporarly changes it to be positive, so we leave it non-const for the 238 | * sake of efficiency. 239 | */ 240 | int fp_exptmod(const fp_int * G, const fp_int * X, const fp_int * P, fp_int * Y) 241 | { 242 | fp_int tmp; 243 | int err; 244 | 245 | #ifdef TFM_CHECK 246 | /* prevent overflows */ 247 | if (P->used > (FP_SIZE/2)) { 248 | return FP_VAL; 249 | } 250 | #endif 251 | 252 | /* is X negative? */ 253 | if (X->sign == FP_NEG) { 254 | /* yes, copy G and invmod it */ 255 | fp_copy(G, &tmp); 256 | if ((err = fp_invmod(&tmp, P, &tmp)) != FP_OKAY) { 257 | return err; 258 | } 259 | #if 0 /* s_fp_exptmod() doesn't look at the sign! */ 260 | X->sign = FP_ZPOS; 261 | #endif 262 | err = s_fp_exptmod(&tmp, X, P, Y); 263 | #if 0 /* X->sign is unchanged... */ 264 | if (X != Y) { 265 | X->sign = FP_NEG; 266 | } 267 | #endif 268 | return err; 269 | } else { 270 | /* Positive exponent so just exptmod */ 271 | return s_fp_exptmod(G, X, P, Y); 272 | } 273 | } 274 | -------------------------------------------------------------------------------- /src/generators/.gitignore: -------------------------------------------------------------------------------- 1 | comba_mont_gen 2 | comba_mult_gen 3 | comba_mult_smallgen 4 | comba_sqr_gen 5 | comba_sqr_smallgen 6 | comba_mont_gen.exe 7 | comba_mult_gen.exe 8 | comba_mult_smallgen.exe 9 | comba_sqr_gen.exe 10 | comba_sqr_smallgen.exe 11 | -------------------------------------------------------------------------------- /src/generators/comba_mont_gen.c: -------------------------------------------------------------------------------- 1 | /* TomsFastMath, a fast ISO C bignum library. -- Tom St Denis */ 2 | /* SPDX-License-Identifier: Unlicense */ 3 | 4 | #include 5 | #include 6 | 7 | int main(int argc, char **argv) 8 | { 9 | int x, y, z, N = 16; 10 | if (argc > 1) N = atoi(argv[1]); 11 | 12 | printf( 13 | #if 1 14 | "/* TomsFastMath, a fast ISO C bignum library. -- Tom St Denis */\n" 15 | "/* SPDX-License-Identifier: Unlicense */\n" 16 | "#ifdef TFM_SMALL_MONT_SET\n" 17 | "/* computes x/R == x (mod N) via Montgomery Reduction */\n" 18 | "void fp_montgomery_reduce_small(fp_int *a, fp_int *m, fp_digit mp)\n" 19 | "{\n" 20 | " fp_digit c[FP_SIZE], *_c, *tmpm, mu, cy;\n" 21 | " int oldused, x, y, pa;\n" 22 | "\n" 23 | "#if defined(USE_MEMSET)\n" 24 | " /* now zero the buff */\n" 25 | " memset(c, 0, sizeof(c));\n" 26 | "#endif\n" 27 | " pa = m->used;\n" 28 | "\n" 29 | " /* copy the input */\n" 30 | " oldused = a->used;\n" 31 | " for (x = 0; x < oldused; x++) {\n" 32 | " c[x] = a->dp[x];\n" 33 | " }\n" 34 | "#if !defined(USE_MEMSET)\n" 35 | " for (; x < 2*pa+3; x++) {\n" 36 | " c[x] = 0;\n" 37 | " }\n" 38 | "#endif\n" 39 | " MONT_START;\n" 40 | #endif 41 | "\n" 42 | " switch (pa) {\n"); 43 | 44 | for (x = 1; x <= N; x++) { 45 | if (x > 16 && (x != 32 && x != 48 && x != 64)) continue; 46 | if (x > 16) printf("#ifdef TFM_HUGE\n"); 47 | 48 | 49 | 50 | printf(" case %d:\n", x); 51 | 52 | for (y = 0; y < x; y++) { 53 | 54 | printf(" x = %d; cy = 0;\n" 55 | " LOOP_START;\n" 56 | " _c = c + %d;\n" 57 | " tmpm = m->dp;\n", y, y); 58 | 59 | printf("#ifdef INNERMUL8\n"); 60 | for (z = 0; z+8 <= x; z += 8) { 61 | printf(" INNERMUL8; _c += 8; tmpm += 8;\n"); 62 | } 63 | for (; z < x; z++) { 64 | printf(" INNERMUL; ++_c;\n"); 65 | } 66 | printf("#else\n"); 67 | for (z = 0; z < x; z++) { 68 | printf(" INNERMUL; ++_c;\n"); 69 | } 70 | printf("#endif\n"); 71 | printf(" LOOP_END;\n" 72 | " while (cy) {\n" 73 | " PROPCARRY;\n" 74 | " ++_c;\n" 75 | " }\n"); 76 | } 77 | //printf(" }\n"); 78 | printf(" break;\n"); 79 | 80 | 81 | 82 | #define LOOP_MACRO(stride) \ 83 | for (x = 0; x < stride; x++) { \ 84 | fp_digit cy = 0; \ 85 | /* get Mu for this round */ \ 86 | LOOP_START; \ 87 | _c = c + x; \ 88 | tmpm = m->dp; \ 89 | for (y = 0; y < stride; y++) { \ 90 | INNERMUL; \ 91 | ++_c; \ 92 | } \ 93 | LOOP_END; \ 94 | while (cy) { \ 95 | PROPCARRY; \ 96 | ++_c; \ 97 | } \ 98 | } 99 | 100 | 101 | 102 | 103 | 104 | if (x > 16) printf("#endif /* TFM_HUGE */\n"); 105 | 106 | 107 | } 108 | 109 | #if 1 110 | 111 | printf( 112 | " }\n" 113 | " /* now copy out */\n" 114 | " _c = c + pa;\n" 115 | " tmpm = a->dp;\n" 116 | " for (x = 0; x < pa+1; x++) {\n" 117 | " *tmpm++ = *_c++;\n" 118 | " }\n" 119 | "\n" 120 | " for (; x < oldused; x++) {\n" 121 | " *tmpm++ = 0;\n" 122 | " }\n" 123 | "\n" 124 | " MONT_FINI;\n" 125 | "\n" 126 | " a->used = pa+1;\n" 127 | " fp_clamp(a);\n" 128 | "\n" 129 | " /* if A >= m then A = A - m */\n" 130 | " if (fp_cmp_mag (a, m) != FP_LT) {\n" 131 | " s_fp_sub (a, m, a);\n" 132 | " }\n" 133 | "}\n\n#endif\n"); 134 | 135 | #endif 136 | 137 | 138 | return 0; 139 | } 140 | -------------------------------------------------------------------------------- /src/generators/comba_mult_gen.c: -------------------------------------------------------------------------------- 1 | /* TomsFastMath, a fast ISO C bignum library. -- Tom St Denis */ 2 | /* SPDX-License-Identifier: Unlicense */ 3 | 4 | /* program emits a NxN comba multiplier */ 5 | #include 6 | #include 7 | 8 | int main(int argc, char **argv) 9 | { 10 | int N, x, y, z; 11 | N = atoi(argv[1]); 12 | 13 | /* print out preamble */ 14 | printf( 15 | "/* TomsFastMath, a fast ISO C bignum library. -- Tom St Denis */\n" 16 | "/* SPDX-License-Identifier: Unlicense */\n" 17 | "#ifndef TFM_PRE_GEN_MPI_C\n" 18 | "#define TFM_DEFINES\n" 19 | "#include \"fp_mul_comba.c\"\n" 20 | "#endif\n" 21 | "\n" 22 | "#if defined(TFM_MUL%d) && FP_SIZE >= %d\n" 23 | "void fp_mul_comba%d(const fp_int *A, const fp_int *B, fp_int *C)\n" 24 | "{\n" 25 | " fp_digit c0, c1, c2, at[%d];\n", N, N+N, N, N+N); 26 | if (N >= 32) { 27 | printf( 28 | " int out_size;\n" 29 | "\n" 30 | " out_size = A->used + B->used;\n"); 31 | } else { 32 | printf( 33 | "\n"); 34 | } 35 | printf( 36 | " memcpy(at, A->dp, %d * sizeof(fp_digit));\n" 37 | " memcpy(at+%d, B->dp, %d * sizeof(fp_digit));\n" 38 | " COMBA_START;\n" 39 | "\n" 40 | " COMBA_CLEAR;\n", N, N, N); 41 | 42 | /* now do the rows */ 43 | for (x = 0; x < (N+N-1); x++) { 44 | printf( 45 | " /* %d */\n", x); 46 | if (x > 0) { 47 | printf( 48 | " COMBA_FORWARD;\n"); 49 | } 50 | for (y = 0; y < N; y++) { 51 | for (z = 0; z < N; z++) { 52 | if ((y+z)==x) { 53 | printf(" MULADD(at[%d], at[%d]);", y, z+N); 54 | } 55 | } 56 | } 57 | printf( 58 | "\n" 59 | " COMBA_STORE(C->dp[%d]);\n", x); 60 | if (N >= 32 && N*2 != (x+2) &&(x+2) >= 40 && (x+2)%8 == 0) { 61 | printf( 62 | "\n" 63 | " /* early out at %d digits, %d*32==%d, or two %d bit operands */\n" 64 | " if (out_size <= %d) { COMBA_STORE2(C->dp[%d]); C->used = %d; C->sign = A->sign ^ B->sign; fp_clamp(C); COMBA_FINI; return; }\n" 65 | "\n" 66 | , x+2, x+2, (x+2)*32, (x+2)*16, x+2, x+1, x+2); 67 | } 68 | } 69 | printf( 70 | " COMBA_STORE2(C->dp[%d]);\n" 71 | " C->used = %d;\n" 72 | " C->sign = A->sign ^ B->sign;\n" 73 | " fp_clamp(C);\n" 74 | " COMBA_FINI;\n" 75 | "}\n#endif\n" 76 | , N+N-1, N+N); 77 | 78 | return 0; 79 | } 80 | -------------------------------------------------------------------------------- /src/generators/comba_mult_smallgen.c: -------------------------------------------------------------------------------- 1 | /* TomsFastMath, a fast ISO C bignum library. -- Tom St Denis */ 2 | /* SPDX-License-Identifier: Unlicense */ 3 | 4 | /* program emits a NxN comba multiplier for 1x1 to 16x16 */ 5 | #include 6 | 7 | int main(int argc, char **argv) 8 | { 9 | int N, x, y, z; 10 | 11 | /* print out preamble */ 12 | printf( 13 | "/* TomsFastMath, a fast ISO C bignum library. -- Tom St Denis */\n" 14 | "/* SPDX-License-Identifier: Unlicense */\n" 15 | "#ifndef TFM_PRE_GEN_MPI_C\n" 16 | "#define TFM_DEFINES\n" 17 | "#include \"fp_mul_comba.c\"\n" 18 | "#endif\n" 19 | "\n" 20 | "#if defined(TFM_SMALL_SET)\n" 21 | "void fp_mul_comba_small(const fp_int *A, const fp_int *B, fp_int *C)\n" 22 | "{\n" 23 | " fp_digit c0, c1, c2, at[32];\n" 24 | " switch (MAX(A->used, B->used)) {\n" 25 | ); 26 | 27 | for (N = 1; N <= 16; N++) { 28 | 29 | printf( 30 | "\n" 31 | " case %d:\n" 32 | " memcpy(at, A->dp, %d * sizeof(fp_digit));\n" 33 | " memcpy(at+%d, B->dp, %d * sizeof(fp_digit));\n" 34 | " COMBA_START;\n" 35 | "\n" 36 | " COMBA_CLEAR;\n", N, N, N, N); 37 | 38 | /* now do the rows */ 39 | for (x = 0; x < (N+N-1); x++) { 40 | printf( 41 | " /* %d */\n", x); 42 | if (x > 0) { 43 | printf( 44 | " COMBA_FORWARD;\n"); 45 | } 46 | printf(" "); 47 | for (y = 0; y < N; y++) { 48 | for (z = 0; z < N; z++) { 49 | if ((y+z)==x) { 50 | printf(" MULADD(at[%d], at[%d]);", y, z+N); 51 | } 52 | } 53 | } 54 | printf( 55 | "\n" 56 | " COMBA_STORE(C->dp[%d]);\n", x); 57 | } 58 | printf( 59 | " COMBA_STORE2(C->dp[%d]);\n" 60 | " C->used = %d;\n" 61 | " C->sign = A->sign ^ B->sign;\n" 62 | " fp_clamp(C);\n" 63 | " COMBA_FINI;\n" 64 | " break;\n", N+N-1, N+N); 65 | } 66 | printf(" }\n}\n\n#endif\n"); 67 | 68 | return 0; 69 | } 70 | -------------------------------------------------------------------------------- /src/generators/comba_sqr_gen.c: -------------------------------------------------------------------------------- 1 | /* TomsFastMath, a fast ISO C bignum library. -- Tom St Denis */ 2 | /* SPDX-License-Identifier: Unlicense */ 3 | 4 | #include 5 | #include 6 | 7 | int main(int argc, char **argv) 8 | { 9 | int x, y, z, N, f; 10 | N = atoi(argv[1]); 11 | 12 | printf( 13 | "/* TomsFastMath, a fast ISO C bignum library. -- Tom St Denis */\n" 14 | "/* SPDX-License-Identifier: Unlicense */\n" 15 | "#ifndef TFM_PRE_GEN_MPI_C\n" 16 | "#define TFM_DEFINES\n" 17 | "#include \"fp_sqr_comba.c\"\n" 18 | "#endif\n" 19 | "\n" 20 | "#if defined(TFM_SQR%d) && FP_SIZE >= %d\n" 21 | "void fp_sqr_comba%d(const fp_int *A, fp_int *B)\n" 22 | "{\n" 23 | " const fp_digit *a;\n" 24 | " fp_digit b[%d], c0, c1, c2;\n", N, N+N, N, N+N); 25 | 26 | if (N > 4) { 27 | printf( 28 | " fp_digit sc0, sc1, sc2;\n"); 29 | } 30 | 31 | printf( 32 | "#ifdef TFM_ISO\n" 33 | " fp_word tt;\n" 34 | "#endif\n" 35 | "\n" 36 | " a = A->dp;\n" 37 | " COMBA_START;\n" 38 | "\n" 39 | " /* clear carries */\n" 40 | " CLEAR_CARRY;\n" 41 | "\n" 42 | " /* output 0 */\n" 43 | " SQRADD(a[0],a[0]);\n" 44 | " COMBA_STORE(b[0]);\n"); 45 | 46 | for (x = 1; x < N+N-1; x++) { 47 | printf( 48 | "\n /* output %d */\n" 49 | " CARRY_FORWARD;\n ", x); 50 | 51 | for (f = y = 0; y < N; y++) { 52 | for (z = 0; z < N; z++) { 53 | if (z != y && z + y == x && y <= z) { 54 | ++f; 55 | } 56 | } 57 | } 58 | 59 | if (f <= 2) { 60 | for (y = 0; y < N; y++) { 61 | for (z = 0; z < N; z++) { 62 | if (y<=z && (y+z)==x) { 63 | if (y == z) { 64 | printf("SQRADD(a[%d], a[%d]); ", y, y); 65 | } else { 66 | printf("SQRADD2(a[%d], a[%d]); ", y, z); 67 | } 68 | } 69 | } 70 | } 71 | } else { 72 | /* new method */ 73 | /* do evens first */ 74 | f = 0; 75 | for (y = 0; y < N; y++) { 76 | for (z = 0; z < N; z++) { 77 | if (z != y && z + y == x && y <= z) { 78 | if (f == 0) { 79 | /* first double */ 80 | printf("SQRADDSC(a[%d], a[%d]); ", y, z); 81 | f = 1; 82 | } else { 83 | printf("SQRADDAC(a[%d], a[%d]); ", y, z); 84 | } 85 | } 86 | } 87 | } 88 | /* forward the carry */ 89 | printf("SQRADDDB; "); 90 | if ((x&1) == 0) { 91 | /* add the square */ 92 | printf("SQRADD(a[%d], a[%d]); ", x/2, x/2); 93 | } 94 | } 95 | printf("\n COMBA_STORE(b[%d]);\n", x); 96 | } 97 | printf(" COMBA_STORE2(b[%d]);\n", N+N-1); 98 | 99 | printf( 100 | " COMBA_FINI;\n" 101 | "\n" 102 | " B->used = %d;\n" 103 | " B->sign = FP_ZPOS;\n" 104 | " memcpy(B->dp, b, %d * sizeof(fp_digit));\n" 105 | " fp_clamp(B);\n" 106 | "}\n#endif\n" 107 | , N+N, N+N); 108 | 109 | return 0; 110 | } 111 | -------------------------------------------------------------------------------- /src/generators/comba_sqr_smallgen.c: -------------------------------------------------------------------------------- 1 | /* TomsFastMath, a fast ISO C bignum library. -- Tom St Denis */ 2 | /* SPDX-License-Identifier: Unlicense */ 3 | 4 | /* Generates squaring comba code... it learns it knows our secrets! */ 5 | #include 6 | 7 | int main(int argc, char **argv) 8 | { 9 | int x, y, z, N, f; 10 | 11 | printf( 12 | "/* TomsFastMath, a fast ISO C bignum library. -- Tom St Denis */\n" 13 | "/* SPDX-License-Identifier: Unlicense */\n" 14 | "#ifndef TFM_PRE_GEN_MPI_C\n" 15 | "#define TFM_DEFINES\n" 16 | "#include \"fp_sqr_comba.c\"\n" 17 | "#endif\n" 18 | "\n" 19 | "#if defined(TFM_SMALL_SET)\n" 20 | "void fp_sqr_comba_small(const fp_int *A, fp_int *B)\n" 21 | "{\n" 22 | " const fp_digit *a;\n" 23 | " fp_digit b[32], c0, c1, c2, sc0, sc1, sc2;\n" 24 | "#ifdef TFM_ISO\n" 25 | " fp_word tt;\n" 26 | "#endif\n" 27 | ); 28 | 29 | printf(" switch (A->used) {\n"); 30 | 31 | for (N = 1; N <= 16; N++) { 32 | printf( 33 | " case %d:\n" 34 | " a = A->dp;\n" 35 | " COMBA_START;\n" 36 | "\n" 37 | " /* clear carries */\n" 38 | " CLEAR_CARRY;\n" 39 | "\n" 40 | " /* output 0 */\n" 41 | " SQRADD(a[0],a[0]);\n" 42 | " COMBA_STORE(b[0]);\n", N); 43 | 44 | for (x = 1; x < N+N-1; x++) { 45 | printf( 46 | "\n /* output %d */\n" 47 | " CARRY_FORWARD;\n ", x); 48 | 49 | for (f = y = 0; y < N; y++) { 50 | for (z = 0; z < N; z++) { 51 | if (z != y && z + y == x && y <= z) { 52 | ++f; 53 | } 54 | } 55 | } 56 | 57 | if (f <= 2) { 58 | for (y = 0; y < N; y++) { 59 | for (z = 0; z < N; z++) { 60 | if (y<=z && (y+z)==x) { 61 | if (y == z) { 62 | printf(" SQRADD(a[%d], a[%d]);", y, y); 63 | } else { 64 | printf(" SQRADD2(a[%d], a[%d]);", y, z); 65 | } 66 | } 67 | } 68 | } 69 | } else { 70 | /* new method */ 71 | /* do evens first */ 72 | f = 0; 73 | for (y = 0; y < N; y++) { 74 | for (z = 0; z < N; z++) { 75 | if (z != y && z + y == x && y <= z) { 76 | if (f == 0) { 77 | /* first double */ 78 | printf(" SQRADDSC(a[%d], a[%d]);", y, z); 79 | f = 1; 80 | } else { 81 | printf(" SQRADDAC(a[%d], a[%d]);", y, z); 82 | } 83 | } 84 | } 85 | } 86 | /* forward the carry */ 87 | printf("SQRADDDB;"); 88 | if ((x&1) == 0) { 89 | /* add the square */ 90 | printf(" SQRADD(a[%d], a[%d]);", x/2, x/2); 91 | } 92 | } 93 | printf("\n COMBA_STORE(b[%d]);\n", x); 94 | } 95 | printf(" COMBA_STORE2(b[%d]);\n", N+N-1); 96 | 97 | printf( 98 | " COMBA_FINI;\n" 99 | "\n" 100 | " B->used = %d;\n" 101 | " B->sign = FP_ZPOS;\n" 102 | " memcpy(B->dp, b, %d * sizeof(fp_digit));\n" 103 | " fp_clamp(B);\n" 104 | " break;\n\n", N+N, N+N); 105 | } 106 | 107 | printf("}\n}\n\n#endif /* TFM_SMALL_SET */\n" 108 | ); 109 | 110 | return 0; 111 | } 112 | -------------------------------------------------------------------------------- /src/generators/makefile: -------------------------------------------------------------------------------- 1 | # TomsFastMath, a fast ISO C bignum library. -- Tom St Denis 2 | # SPDX-License-Identifier: Unlicense 3 | 4 | all: comba_sqr_gen comba_sqr_smallgen 5 | 6 | clean: 7 | rm -f comba_mont_gen 8 | rm -f comba_mont_gen.exe 9 | rm -f comba_mult_gen 10 | rm -f comba_mult_gen.exe 11 | rm -f comba_mult_smallgen 12 | rm -f comba_mult_smallgen.exe 13 | rm -f comba_sqr_gen 14 | rm -f comba_sqr_gen.exe 15 | rm -f comba_sqr_smallgen 16 | rm -f comba_sqr_smallgen.exe 17 | 18 | comba_mont_gen: comba_mont_gen.c 19 | gcc -o comba_mont_gen comba_mont_gen.c 20 | comba_mult_gen: comba_mult_gen.c 21 | gcc -o comba_mult_gen comba_mult_gen.c 22 | comba_mult_smallgen: comba_mult_smallgen.c 23 | gcc -o comba_mult_smallgen comba_mult_smallgen.c 24 | comba_sqr_gen: comba_sqr_gen.c 25 | gcc -o comba_sqr_gen comba_sqr_gen.c 26 | comba_sqr_smallgen: comba_sqr_smallgen.c 27 | gcc -o comba_sqr_smallgen comba_sqr_smallgen.c 28 | 29 | regen: comba_mont_gen comba_mult_gen comba_mult_smallgen comba_sqr_gen comba_sqr_smallgen 30 | ./comba_mont_gen > ../mont/fp_mont_small.i 31 | for i in 3 4 6 7 8 9 12 17 20 24 28 32 48 64; do \ 32 | ./comba_mult_gen $$i | sed -e 's/ *$$//' > ../mul/fp_mul_comba_$$i.c; \ 33 | done 34 | ./comba_mult_smallgen > ../mul/fp_mul_comba_small_set.c 35 | for i in 3 4 6 7 8 9 12 17 20 24 28 32 48 64; do \ 36 | ./comba_sqr_gen $$i | sed -e 's/ *$$//' > ../sqr/fp_sqr_comba_$$i.c; \ 37 | done 38 | ./comba_sqr_smallgen > ../sqr/fp_sqr_comba_small_set.c 39 | -------------------------------------------------------------------------------- /src/headers/tfm_private.h: -------------------------------------------------------------------------------- 1 | /* TomsFastMath, a fast ISO C bignum library. -- Tom St Denis */ 2 | /* SPDX-License-Identifier: Unlicense */ 3 | #ifndef TFM_PRIVATE_H_ 4 | #define TFM_PRIVATE_H_ 5 | 6 | #include "tfm.h" 7 | 8 | /* 9 | * Private symbols 10 | * --------------- 11 | * 12 | * On Unix symbols can be marked as hidden if tomsfastmath is compiled 13 | * as a shared object. By default, symbols are visible. 14 | */ 15 | #if defined(__GNUC__) && __GNUC__ >= 4 && !defined(_WIN32) && !defined(__CYGWIN__) 16 | # define FP_PRIVATE __attribute__ ((visibility ("hidden"))) 17 | #else 18 | # define FP_PRIVATE 19 | #endif 20 | 21 | /* VARIOUS LOW LEVEL STUFFS */ 22 | FP_PRIVATE void s_fp_add(const fp_int *a, const fp_int *b, fp_int *c); 23 | FP_PRIVATE void s_fp_sub(const fp_int *a, const fp_int *b, fp_int *c); 24 | FP_PRIVATE void fp_reverse(unsigned char *s, int len); 25 | 26 | FP_PRIVATE void fp_mul_comba(const fp_int *A, const fp_int *B, fp_int *C); 27 | 28 | #ifdef TFM_SMALL_SET 29 | FP_PRIVATE void fp_mul_comba_small(const fp_int *A, const fp_int *B, fp_int *C); 30 | #endif 31 | 32 | #ifdef TFM_MUL3 33 | FP_PRIVATE void fp_mul_comba3(const fp_int *A, const fp_int *B, fp_int *C); 34 | #endif 35 | #ifdef TFM_MUL4 36 | FP_PRIVATE void fp_mul_comba4(const fp_int *A, const fp_int *B, fp_int *C); 37 | #endif 38 | #ifdef TFM_MUL6 39 | FP_PRIVATE void fp_mul_comba6(const fp_int *A, const fp_int *B, fp_int *C); 40 | #endif 41 | #ifdef TFM_MUL7 42 | FP_PRIVATE void fp_mul_comba7(const fp_int *A, const fp_int *B, fp_int *C); 43 | #endif 44 | #ifdef TFM_MUL8 45 | FP_PRIVATE void fp_mul_comba8(const fp_int *A, const fp_int *B, fp_int *C); 46 | #endif 47 | #ifdef TFM_MUL9 48 | FP_PRIVATE void fp_mul_comba9(const fp_int *A, const fp_int *B, fp_int *C); 49 | #endif 50 | #ifdef TFM_MUL12 51 | FP_PRIVATE void fp_mul_comba12(const fp_int *A, const fp_int *B, fp_int *C); 52 | #endif 53 | #ifdef TFM_MUL17 54 | FP_PRIVATE void fp_mul_comba17(const fp_int *A, const fp_int *B, fp_int *C); 55 | #endif 56 | 57 | #ifdef TFM_MUL20 58 | FP_PRIVATE void fp_mul_comba20(const fp_int *A, const fp_int *B, fp_int *C); 59 | #endif 60 | #ifdef TFM_MUL24 61 | FP_PRIVATE void fp_mul_comba24(const fp_int *A, const fp_int *B, fp_int *C); 62 | #endif 63 | #ifdef TFM_MUL28 64 | FP_PRIVATE void fp_mul_comba28(const fp_int *A, const fp_int *B, fp_int *C); 65 | #endif 66 | #ifdef TFM_MUL32 67 | FP_PRIVATE void fp_mul_comba32(const fp_int *A, const fp_int *B, fp_int *C); 68 | #endif 69 | #ifdef TFM_MUL48 70 | FP_PRIVATE void fp_mul_comba48(const fp_int *A, const fp_int *B, fp_int *C); 71 | #endif 72 | #ifdef TFM_MUL64 73 | FP_PRIVATE void fp_mul_comba64(const fp_int *A, const fp_int *B, fp_int *C); 74 | #endif 75 | 76 | FP_PRIVATE void fp_sqr_comba(const fp_int *A, fp_int *B); 77 | 78 | #ifdef TFM_SMALL_SET 79 | FP_PRIVATE void fp_sqr_comba_small(const fp_int *A, fp_int *B); 80 | #endif 81 | 82 | #ifdef TFM_SQR3 83 | FP_PRIVATE void fp_sqr_comba3(const fp_int *A, fp_int *B); 84 | #endif 85 | #ifdef TFM_SQR4 86 | FP_PRIVATE void fp_sqr_comba4(const fp_int *A, fp_int *B); 87 | #endif 88 | #ifdef TFM_SQR6 89 | FP_PRIVATE void fp_sqr_comba6(const fp_int *A, fp_int *B); 90 | #endif 91 | #ifdef TFM_SQR7 92 | FP_PRIVATE void fp_sqr_comba7(const fp_int *A, fp_int *B); 93 | #endif 94 | #ifdef TFM_SQR8 95 | FP_PRIVATE void fp_sqr_comba8(const fp_int *A, fp_int *B); 96 | #endif 97 | #ifdef TFM_SQR9 98 | FP_PRIVATE void fp_sqr_comba9(const fp_int *A, fp_int *B); 99 | #endif 100 | #ifdef TFM_SQR12 101 | FP_PRIVATE void fp_sqr_comba12(const fp_int *A, fp_int *B); 102 | #endif 103 | #ifdef TFM_SQR17 104 | FP_PRIVATE void fp_sqr_comba17(const fp_int *A, fp_int *B); 105 | #endif 106 | 107 | #ifdef TFM_SQR20 108 | FP_PRIVATE void fp_sqr_comba20(const fp_int *A, fp_int *B); 109 | #endif 110 | #ifdef TFM_SQR24 111 | FP_PRIVATE void fp_sqr_comba24(const fp_int *A, fp_int *B); 112 | #endif 113 | #ifdef TFM_SQR28 114 | FP_PRIVATE void fp_sqr_comba28(const fp_int *A, fp_int *B); 115 | #endif 116 | #ifdef TFM_SQR32 117 | FP_PRIVATE void fp_sqr_comba32(const fp_int *A, fp_int *B); 118 | #endif 119 | #ifdef TFM_SQR48 120 | FP_PRIVATE void fp_sqr_comba48(const fp_int *A, fp_int *B); 121 | #endif 122 | #ifdef TFM_SQR64 123 | FP_PRIVATE void fp_sqr_comba64(const fp_int *A, fp_int *B); 124 | #endif 125 | FP_PRIVATE extern const char *fp_s_rmap; 126 | 127 | #endif 128 | -------------------------------------------------------------------------------- /src/misc/fp_ident.c: -------------------------------------------------------------------------------- 1 | /* TomsFastMath, a fast ISO C bignum library. -- Tom St Denis */ 2 | /* SPDX-License-Identifier: Unlicense */ 3 | #include 4 | 5 | #ifndef GIT_VERSION 6 | #define GIT_VERSION TFM_VERSION_S 7 | #endif 8 | 9 | #define dnstrcon_direct(D, N, S) do { dnmemcpy((D), (N), S, sizeof(S)-1); } while(0) 10 | #define dnstrcon(D, N, S) do { if (dnmemcpy((D), (N), S, sizeof(S)-1) == -1) goto err_out; } while(0) 11 | static signed long dnmemcpy(char **d, size_t *n, const char *s, size_t len) { 12 | if (len >= *n) return -1; 13 | memcpy(*d, s, len); 14 | *n -= len; 15 | *d += len; 16 | **d = '\0'; 17 | return len; 18 | } 19 | 20 | /* log(2)/log(10) ~= 0.30102999... ~= 30103 / 100000 21 | * we need to add one byte because this rounds to zero, and one for sign 22 | * these provide exact answer for integers up to 4720 bytes wide... */ 23 | #define U_DIGITS(T) (1 + ((sizeof(T) * 8UL) * 30103UL) / 100000UL) 24 | #define S_DIGITS(T) (2 + ((sizeof(T) * 8UL - 1) * 30103UL) / 100000UL) 25 | 26 | #define dnstrul(D, N, V) do { if (dnstrul_impl((D), (N), (V)) == -1) goto err_out; } while(0) 27 | static signed long dnstrul_impl(char **d, size_t *n, unsigned long value) { 28 | char digits[U_DIGITS(unsigned long)+1]; /* fit digits plus null byte */ 29 | char *digit = digits + (sizeof(digits) - 1); 30 | size_t len = 0; 31 | *digit = '\0'; 32 | do { 33 | *--digit = '0' + (value % 10); 34 | value /= 10; 35 | ++len; 36 | if (digit < digits) return -1; 37 | } while (value); 38 | if (len >= *n) return -1; 39 | return dnmemcpy(d, n, digit, len); 40 | } 41 | 42 | const char *fp_ident(void) 43 | { 44 | static char buf[512]; 45 | char *d = buf; 46 | size_t n = sizeof(buf); 47 | 48 | dnstrcon(&d, &n, 49 | "TomsFastMath " GIT_VERSION "\n" 50 | #if defined(TFM_IDENT_BUILD_DATE) 51 | "Built on " __DATE__ " at " __TIME__ "\n" 52 | #endif 53 | "\n" 54 | "Sizeofs\n" 55 | "\tfp_digit = " 56 | ); 57 | dnstrul(&d, &n, sizeof(fp_digit)); 58 | dnstrcon(&d, &n, 59 | "\n" 60 | "\tfp_word = " 61 | ); 62 | dnstrul(&d, &n, sizeof(fp_word)); 63 | dnstrcon(&d, &n, 64 | "\n\n" 65 | "FP_MAX_SIZE = " 66 | ); 67 | dnstrul(&d, &n, FP_MAX_SIZE); 68 | dnstrcon(&d, &n, 69 | "\n" 70 | "SIZEOF_FP_DIGIT = " 71 | ); 72 | dnstrul(&d, &n, SIZEOF_FP_DIGIT); 73 | dnstrcon(&d, &n, 74 | "\n" 75 | "DIGIT_SHIFT = " 76 | ); 77 | dnstrul(&d, &n, DIGIT_SHIFT); 78 | dnstrcon(&d, &n, 79 | "\n\n" 80 | "Defines: \n" 81 | #ifdef __i386__ 82 | " __i386__ " 83 | #endif 84 | #ifdef __x86_64__ 85 | " __x86_64__ " 86 | #endif 87 | #ifdef TFM_X86 88 | " TFM_X86 " 89 | #endif 90 | #ifdef TFM_X86_64 91 | " TFM_X86_64 " 92 | #endif 93 | #ifdef TFM_SSE2 94 | " TFM_SSE2 " 95 | #endif 96 | #ifdef TFM_ARM 97 | " TFM_ARM " 98 | #endif 99 | #ifdef TFM_PPC32 100 | " TFM_PPC32 " 101 | #endif 102 | #ifdef TFM_AVR32 103 | " TFM_AVR32 " 104 | #endif 105 | #ifdef TFM_ECC192 106 | " TFM_ECC192 " 107 | #endif 108 | #ifdef TFM_ECC224 109 | " TFM_ECC224 " 110 | #endif 111 | #ifdef TFM_ECC384 112 | " TFM_ECC384 " 113 | #endif 114 | #ifdef TFM_ECC521 115 | " TFM_ECC521 " 116 | #endif 117 | 118 | #ifdef TFM_NO_ASM 119 | " TFM_NO_ASM " 120 | #endif 121 | #ifdef FP_64BIT 122 | " FP_64BIT " 123 | #endif 124 | #ifdef TFM_HUGE 125 | " TFM_HUGE " 126 | #endif 127 | "\n" 128 | ); 129 | 130 | if (sizeof(fp_digit) == sizeof(fp_word)) { 131 | dnstrcon(&d, &n, 132 | "WARNING: sizeof(fp_digit) == sizeof(fp_word)," 133 | " this build is likely to not work properly.\n" 134 | ); 135 | } 136 | 137 | memset(d, 0, n); 138 | return buf; 139 | err_out: 140 | d = buf; 141 | n = sizeof(buf); 142 | *d = '\0'; 143 | 144 | dnstrcon_direct(&d, &n, 145 | "ERROR: Buffer too small.\n" 146 | ); 147 | 148 | return buf; 149 | } 150 | 151 | #ifdef STANDALONE 152 | 153 | int main(void) 154 | { 155 | const char* ident = fp_ident(); 156 | printf("%s\n", ident); 157 | printf("ident len: %lu\n", (unsigned long)strlen(ident)); 158 | return 0; 159 | } 160 | 161 | #endif 162 | -------------------------------------------------------------------------------- /src/misc/fp_rand.c: -------------------------------------------------------------------------------- 1 | /* TomsFastMath, a fast ISO C bignum library. -- Tom St Denis */ 2 | /* SPDX-License-Identifier: Unlicense */ 3 | #include 4 | 5 | #if FP_GEN_RANDOM_MAX == 0xffffffff 6 | #define FP_GEN_RANDOM_SHIFT 32 7 | #elif FP_GEN_RANDOM_MAX == 32767 8 | /* SHRT_MAX */ 9 | #define FP_GEN_RANDOM_SHIFT 15 10 | #elif FP_GEN_RANDOM_MAX == 2147483647 11 | /* INT_MAX */ 12 | #define FP_GEN_RANDOM_SHIFT 31 13 | #elif !defined(FP_GEN_RANDOM_SHIFT) 14 | #error Thou shalt define their own valid FP_GEN_RANDOM_SHIFT 15 | #endif 16 | 17 | /* makes a pseudo-random int of a given size */ 18 | static fp_digit fp_gen_random(void) 19 | { 20 | fp_digit d = 0, msk = 0; 21 | do { 22 | d <<= FP_GEN_RANDOM_SHIFT; 23 | d |= ((fp_digit) FP_GEN_RANDOM()); 24 | msk <<= FP_GEN_RANDOM_SHIFT; 25 | msk |= FP_GEN_RANDOM_MAX; 26 | } while ((FP_MASK & msk) != FP_MASK); 27 | d &= FP_MASK; 28 | return d; 29 | } 30 | 31 | void fp_rand(fp_int *a, int digits) 32 | { 33 | fp_digit d; 34 | 35 | fp_zero(a); 36 | if (digits <= 0) { 37 | return; 38 | } 39 | 40 | /* first place a random non-zero digit */ 41 | do { 42 | d = fp_gen_random(); 43 | } while (d == 0); 44 | 45 | fp_add_d (a, d, a); 46 | 47 | while (--digits > 0) { 48 | fp_lshd (a, 1); 49 | fp_add_d (a, fp_gen_random(), a); 50 | } 51 | 52 | return; 53 | 54 | } 55 | -------------------------------------------------------------------------------- /src/misc/fp_set.c: -------------------------------------------------------------------------------- 1 | /* TomsFastMath, a fast ISO C bignum library. -- Tom St Denis */ 2 | /* SPDX-License-Identifier: Unlicense */ 3 | #include 4 | 5 | void fp_set(fp_int *a, fp_digit b) 6 | { 7 | fp_zero(a); 8 | a->dp[0] = b; 9 | a->used = a->dp[0] ? 1 : 0; 10 | } 11 | -------------------------------------------------------------------------------- /src/mont/fp_montgomery_calc_normalization.c: -------------------------------------------------------------------------------- 1 | /* TomsFastMath, a fast ISO C bignum library. -- Tom St Denis */ 2 | /* SPDX-License-Identifier: Unlicense */ 3 | #include 4 | 5 | /* computes a = B**n mod b without division or multiplication useful for 6 | * normalizing numbers in a Montgomery system. 7 | */ 8 | void fp_montgomery_calc_normalization(fp_int *a, const fp_int *b) 9 | { 10 | int x, bits; 11 | 12 | /* how many bits of last digit does b use */ 13 | bits = fp_count_bits (b) % DIGIT_BIT; 14 | if (!bits) bits = DIGIT_BIT; 15 | 16 | /* compute A = B^(n-1) * 2^(bits-1) */ 17 | if (b->used > 1) { 18 | fp_2expt (a, (b->used - 1) * DIGIT_BIT + bits - 1); 19 | } else { 20 | fp_set(a, 1); 21 | bits = 1; 22 | } 23 | 24 | /* now compute C = A * B mod b */ 25 | for (x = bits - 1; x < (int)DIGIT_BIT; x++) { 26 | fp_mul_2 (a, a); 27 | if (fp_cmp_mag (a, b) != FP_LT) { 28 | s_fp_sub (a, b, a); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/mont/fp_montgomery_setup.c: -------------------------------------------------------------------------------- 1 | /* TomsFastMath, a fast ISO C bignum library. -- Tom St Denis */ 2 | /* SPDX-License-Identifier: Unlicense */ 3 | #include 4 | 5 | /* setups the montgomery reduction */ 6 | int fp_montgomery_setup(const fp_int *a, fp_digit *rho) 7 | { 8 | fp_digit x, b; 9 | 10 | /* fast inversion mod 2**k 11 | * 12 | * Based on the fact that 13 | * 14 | * XA = 1 (mod 2**n) => (X(2-XA)) A = 1 (mod 2**2n) 15 | * => 2*X*A - X*X*A*A = 1 16 | * => 2*(1) - (1) = 1 17 | */ 18 | b = a->dp[0]; 19 | 20 | if ((b & 1) == 0) { 21 | return FP_VAL; 22 | } 23 | 24 | x = (((b + 2) & 4) << 1) + b; /* here x*a==1 mod 2**4 */ 25 | x *= 2 - b * x; /* here x*a==1 mod 2**8 */ 26 | x *= 2 - b * x; /* here x*a==1 mod 2**16 */ 27 | x *= 2 - b * x; /* here x*a==1 mod 2**32 */ 28 | #ifdef FP_64BIT 29 | x *= 2 - b * x; /* here x*a==1 mod 2**64 */ 30 | #endif 31 | 32 | /* rho = -1/m mod b */ 33 | *rho = (((fp_word) 1 << ((fp_word) DIGIT_BIT)) - ((fp_word)x)); 34 | 35 | return FP_OKAY; 36 | } 37 | -------------------------------------------------------------------------------- /src/mul/fp_mul.c: -------------------------------------------------------------------------------- 1 | /* TomsFastMath, a fast ISO C bignum library. -- Tom St Denis */ 2 | /* SPDX-License-Identifier: Unlicense */ 3 | #include 4 | 5 | /* c = a * b */ 6 | void fp_mul(const fp_int *A, const fp_int *B, fp_int *C) 7 | { 8 | int y, old_used; 9 | #if FP_SIZE >= 48 10 | int yy; 11 | #endif 12 | 13 | old_used = C->used; 14 | 15 | /* call generic if we're out of range */ 16 | if (A->used + B->used > FP_SIZE) { 17 | fp_mul_comba(A, B, C); 18 | goto clean; 19 | } 20 | 21 | y = MAX(A->used, B->used); 22 | #if FP_SIZE >= 48 23 | yy = MIN(A->used, B->used); 24 | #endif 25 | /* pick a comba (unrolled 4/8/16/32 x or rolled) based on the size 26 | of the largest input. We also want to avoid doing excess mults if the 27 | inputs are not close to the next power of two. That is, for example, 28 | if say y=17 then we would do (32-17)^2 = 225 unneeded multiplications 29 | */ 30 | 31 | #if defined(TFM_MUL3) && FP_SIZE >= 6 32 | if (y <= 3) { 33 | fp_mul_comba3(A,B,C); 34 | goto clean; 35 | } 36 | #endif 37 | #if defined(TFM_MUL4) && FP_SIZE >= 8 38 | if (y == 4) { 39 | fp_mul_comba4(A,B,C); 40 | goto clean; 41 | } 42 | #endif 43 | #if defined(TFM_MUL6) && FP_SIZE >= 12 44 | if (y <= 6) { 45 | fp_mul_comba6(A,B,C); 46 | goto clean; 47 | } 48 | #endif 49 | #if defined(TFM_MUL7) && FP_SIZE >= 14 50 | if (y == 7) { 51 | fp_mul_comba7(A,B,C); 52 | goto clean; 53 | } 54 | #endif 55 | #if defined(TFM_MUL8) && FP_SIZE >= 16 56 | if (y == 8) { 57 | fp_mul_comba8(A,B,C); 58 | goto clean; 59 | } 60 | #endif 61 | #if defined(TFM_MUL9) && FP_SIZE >= 18 62 | if (y == 9) { 63 | fp_mul_comba9(A,B,C); 64 | goto clean; 65 | } 66 | #endif 67 | #if defined(TFM_MUL12) && FP_SIZE >= 24 68 | if (y <= 12) { 69 | fp_mul_comba12(A,B,C); 70 | goto clean; 71 | } 72 | #endif 73 | #if defined(TFM_MUL17) && FP_SIZE >= 34 74 | if (y <= 17) { 75 | fp_mul_comba17(A,B,C); 76 | goto clean; 77 | } 78 | #endif 79 | 80 | #if defined(TFM_SMALL_SET) && FP_SIZE >= 32 81 | if (y <= 16) { 82 | fp_mul_comba_small(A,B,C); 83 | goto clean; 84 | } 85 | #endif 86 | #if defined(TFM_MUL20) && FP_SIZE >= 40 87 | if (y <= 20) { 88 | fp_mul_comba20(A,B,C); 89 | goto clean; 90 | } 91 | #endif 92 | #if defined(TFM_MUL24) && FP_SIZE >= 48 93 | if (yy >= 16 && y <= 24) { 94 | fp_mul_comba24(A,B,C); 95 | goto clean; 96 | } 97 | #endif 98 | #if defined(TFM_MUL28) && FP_SIZE >= 56 99 | if (yy >= 20 && y <= 28) { 100 | fp_mul_comba28(A,B,C); 101 | goto clean; 102 | } 103 | #endif 104 | #if defined(TFM_MUL32) && FP_SIZE >= 64 105 | if (yy >= 24 && y <= 32) { 106 | fp_mul_comba32(A,B,C); 107 | goto clean; 108 | } 109 | #endif 110 | #if defined(TFM_MUL48) && FP_SIZE >= 96 111 | if (yy >= 40 && y <= 48) { 112 | fp_mul_comba48(A,B,C); 113 | goto clean; 114 | } 115 | #endif 116 | #if defined(TFM_MUL64) && FP_SIZE >= 128 117 | if (yy >= 56 && y <= 64) { 118 | fp_mul_comba64(A,B,C); 119 | goto clean; 120 | } 121 | #endif 122 | fp_mul_comba(A,B,C); 123 | clean: 124 | for (y = C->used; y < old_used; y++) { 125 | C->dp[y] = 0; 126 | } 127 | } 128 | -------------------------------------------------------------------------------- /src/mul/fp_mul_2.c: -------------------------------------------------------------------------------- 1 | /* TomsFastMath, a fast ISO C bignum library. -- Tom St Denis */ 2 | /* SPDX-License-Identifier: Unlicense */ 3 | #include 4 | 5 | void fp_mul_2(const fp_int * a, fp_int * b) 6 | { 7 | int x, oldused; 8 | 9 | oldused = b->used; 10 | b->used = a->used; 11 | 12 | { 13 | register const fp_digit *tmpa; 14 | register fp_digit r, rr, *tmpb; 15 | 16 | /* alias for source */ 17 | tmpa = a->dp; 18 | 19 | /* alias for dest */ 20 | tmpb = b->dp; 21 | 22 | /* carry */ 23 | r = 0; 24 | for (x = 0; x < a->used; x++) { 25 | 26 | /* get what will be the *next* carry bit from the 27 | * MSB of the current digit 28 | */ 29 | rr = *tmpa >> ((fp_digit)(DIGIT_BIT - 1)); 30 | 31 | /* now shift up this digit, add in the carry [from the previous] */ 32 | *tmpb++ = ((*tmpa++ << ((fp_digit)1)) | r); 33 | 34 | /* copy the carry that would be from the source 35 | * digit into the next iteration 36 | */ 37 | r = rr; 38 | } 39 | 40 | /* new leading digit? */ 41 | if (r != 0 && b->used != (FP_SIZE-1)) { 42 | /* add a MSB which is always 1 at this point */ 43 | *tmpb = 1; 44 | ++(b->used); 45 | } 46 | 47 | /* now zero any excess digits on the destination 48 | * that we didn't write to 49 | */ 50 | tmpb = b->dp + b->used; 51 | for (x = b->used; x < oldused; x++) { 52 | *tmpb++ = 0; 53 | } 54 | } 55 | b->sign = a->sign; 56 | } 57 | -------------------------------------------------------------------------------- /src/mul/fp_mul_2d.c: -------------------------------------------------------------------------------- 1 | /* TomsFastMath, a fast ISO C bignum library. -- Tom St Denis */ 2 | /* SPDX-License-Identifier: Unlicense */ 3 | #include 4 | 5 | /* c = a * 2**d */ 6 | void fp_mul_2d(const fp_int *a, int b, fp_int *c) 7 | { 8 | fp_digit carry, carrytmp, shift; 9 | int x; 10 | 11 | /* copy it */ 12 | fp_copy(a, c); 13 | 14 | /* handle whole digits */ 15 | if (b >= DIGIT_BIT) { 16 | fp_lshd(c, b/DIGIT_BIT); 17 | } 18 | b %= DIGIT_BIT; 19 | 20 | /* shift the digits */ 21 | if (b != 0) { 22 | carry = 0; 23 | shift = DIGIT_BIT - b; 24 | for (x = 0; x < c->used; x++) { 25 | carrytmp = c->dp[x] >> shift; 26 | c->dp[x] = (c->dp[x] << b) + carry; 27 | carry = carrytmp; 28 | } 29 | /* store last carry if room */ 30 | if (carry && x < FP_SIZE) { 31 | c->dp[c->used++] = carry; 32 | } 33 | } 34 | fp_clamp(c); 35 | } 36 | -------------------------------------------------------------------------------- /src/mul/fp_mul_comba_12.c: -------------------------------------------------------------------------------- 1 | /* TomsFastMath, a fast ISO C bignum library. -- Tom St Denis */ 2 | /* SPDX-License-Identifier: Unlicense */ 3 | #ifndef TFM_PRE_GEN_MPI_C 4 | #define TFM_DEFINES 5 | #include "fp_mul_comba.c" 6 | #endif 7 | 8 | #if defined(TFM_MUL12) && FP_SIZE >= 24 9 | void fp_mul_comba12(const fp_int *A, const fp_int *B, fp_int *C) 10 | { 11 | fp_digit c0, c1, c2, at[24]; 12 | 13 | memcpy(at, A->dp, 12 * sizeof(fp_digit)); 14 | memcpy(at+12, B->dp, 12 * sizeof(fp_digit)); 15 | COMBA_START; 16 | 17 | COMBA_CLEAR; 18 | /* 0 */ 19 | MULADD(at[0], at[12]); 20 | COMBA_STORE(C->dp[0]); 21 | /* 1 */ 22 | COMBA_FORWARD; 23 | MULADD(at[0], at[13]); MULADD(at[1], at[12]); 24 | COMBA_STORE(C->dp[1]); 25 | /* 2 */ 26 | COMBA_FORWARD; 27 | MULADD(at[0], at[14]); MULADD(at[1], at[13]); MULADD(at[2], at[12]); 28 | COMBA_STORE(C->dp[2]); 29 | /* 3 */ 30 | COMBA_FORWARD; 31 | MULADD(at[0], at[15]); MULADD(at[1], at[14]); MULADD(at[2], at[13]); MULADD(at[3], at[12]); 32 | COMBA_STORE(C->dp[3]); 33 | /* 4 */ 34 | COMBA_FORWARD; 35 | MULADD(at[0], at[16]); MULADD(at[1], at[15]); MULADD(at[2], at[14]); MULADD(at[3], at[13]); MULADD(at[4], at[12]); 36 | COMBA_STORE(C->dp[4]); 37 | /* 5 */ 38 | COMBA_FORWARD; 39 | MULADD(at[0], at[17]); MULADD(at[1], at[16]); MULADD(at[2], at[15]); MULADD(at[3], at[14]); MULADD(at[4], at[13]); MULADD(at[5], at[12]); 40 | COMBA_STORE(C->dp[5]); 41 | /* 6 */ 42 | COMBA_FORWARD; 43 | MULADD(at[0], at[18]); MULADD(at[1], at[17]); MULADD(at[2], at[16]); MULADD(at[3], at[15]); MULADD(at[4], at[14]); MULADD(at[5], at[13]); MULADD(at[6], at[12]); 44 | COMBA_STORE(C->dp[6]); 45 | /* 7 */ 46 | COMBA_FORWARD; 47 | MULADD(at[0], at[19]); MULADD(at[1], at[18]); MULADD(at[2], at[17]); MULADD(at[3], at[16]); MULADD(at[4], at[15]); MULADD(at[5], at[14]); MULADD(at[6], at[13]); MULADD(at[7], at[12]); 48 | COMBA_STORE(C->dp[7]); 49 | /* 8 */ 50 | COMBA_FORWARD; 51 | MULADD(at[0], at[20]); MULADD(at[1], at[19]); MULADD(at[2], at[18]); MULADD(at[3], at[17]); MULADD(at[4], at[16]); MULADD(at[5], at[15]); MULADD(at[6], at[14]); MULADD(at[7], at[13]); MULADD(at[8], at[12]); 52 | COMBA_STORE(C->dp[8]); 53 | /* 9 */ 54 | COMBA_FORWARD; 55 | MULADD(at[0], at[21]); MULADD(at[1], at[20]); MULADD(at[2], at[19]); MULADD(at[3], at[18]); MULADD(at[4], at[17]); MULADD(at[5], at[16]); MULADD(at[6], at[15]); MULADD(at[7], at[14]); MULADD(at[8], at[13]); MULADD(at[9], at[12]); 56 | COMBA_STORE(C->dp[9]); 57 | /* 10 */ 58 | COMBA_FORWARD; 59 | MULADD(at[0], at[22]); MULADD(at[1], at[21]); MULADD(at[2], at[20]); MULADD(at[3], at[19]); MULADD(at[4], at[18]); MULADD(at[5], at[17]); MULADD(at[6], at[16]); MULADD(at[7], at[15]); MULADD(at[8], at[14]); MULADD(at[9], at[13]); MULADD(at[10], at[12]); 60 | COMBA_STORE(C->dp[10]); 61 | /* 11 */ 62 | COMBA_FORWARD; 63 | MULADD(at[0], at[23]); MULADD(at[1], at[22]); MULADD(at[2], at[21]); MULADD(at[3], at[20]); MULADD(at[4], at[19]); MULADD(at[5], at[18]); MULADD(at[6], at[17]); MULADD(at[7], at[16]); MULADD(at[8], at[15]); MULADD(at[9], at[14]); MULADD(at[10], at[13]); MULADD(at[11], at[12]); 64 | COMBA_STORE(C->dp[11]); 65 | /* 12 */ 66 | COMBA_FORWARD; 67 | MULADD(at[1], at[23]); MULADD(at[2], at[22]); MULADD(at[3], at[21]); MULADD(at[4], at[20]); MULADD(at[5], at[19]); MULADD(at[6], at[18]); MULADD(at[7], at[17]); MULADD(at[8], at[16]); MULADD(at[9], at[15]); MULADD(at[10], at[14]); MULADD(at[11], at[13]); 68 | COMBA_STORE(C->dp[12]); 69 | /* 13 */ 70 | COMBA_FORWARD; 71 | MULADD(at[2], at[23]); MULADD(at[3], at[22]); MULADD(at[4], at[21]); MULADD(at[5], at[20]); MULADD(at[6], at[19]); MULADD(at[7], at[18]); MULADD(at[8], at[17]); MULADD(at[9], at[16]); MULADD(at[10], at[15]); MULADD(at[11], at[14]); 72 | COMBA_STORE(C->dp[13]); 73 | /* 14 */ 74 | COMBA_FORWARD; 75 | MULADD(at[3], at[23]); MULADD(at[4], at[22]); MULADD(at[5], at[21]); MULADD(at[6], at[20]); MULADD(at[7], at[19]); MULADD(at[8], at[18]); MULADD(at[9], at[17]); MULADD(at[10], at[16]); MULADD(at[11], at[15]); 76 | COMBA_STORE(C->dp[14]); 77 | /* 15 */ 78 | COMBA_FORWARD; 79 | MULADD(at[4], at[23]); MULADD(at[5], at[22]); MULADD(at[6], at[21]); MULADD(at[7], at[20]); MULADD(at[8], at[19]); MULADD(at[9], at[18]); MULADD(at[10], at[17]); MULADD(at[11], at[16]); 80 | COMBA_STORE(C->dp[15]); 81 | /* 16 */ 82 | COMBA_FORWARD; 83 | MULADD(at[5], at[23]); MULADD(at[6], at[22]); MULADD(at[7], at[21]); MULADD(at[8], at[20]); MULADD(at[9], at[19]); MULADD(at[10], at[18]); MULADD(at[11], at[17]); 84 | COMBA_STORE(C->dp[16]); 85 | /* 17 */ 86 | COMBA_FORWARD; 87 | MULADD(at[6], at[23]); MULADD(at[7], at[22]); MULADD(at[8], at[21]); MULADD(at[9], at[20]); MULADD(at[10], at[19]); MULADD(at[11], at[18]); 88 | COMBA_STORE(C->dp[17]); 89 | /* 18 */ 90 | COMBA_FORWARD; 91 | MULADD(at[7], at[23]); MULADD(at[8], at[22]); MULADD(at[9], at[21]); MULADD(at[10], at[20]); MULADD(at[11], at[19]); 92 | COMBA_STORE(C->dp[18]); 93 | /* 19 */ 94 | COMBA_FORWARD; 95 | MULADD(at[8], at[23]); MULADD(at[9], at[22]); MULADD(at[10], at[21]); MULADD(at[11], at[20]); 96 | COMBA_STORE(C->dp[19]); 97 | /* 20 */ 98 | COMBA_FORWARD; 99 | MULADD(at[9], at[23]); MULADD(at[10], at[22]); MULADD(at[11], at[21]); 100 | COMBA_STORE(C->dp[20]); 101 | /* 21 */ 102 | COMBA_FORWARD; 103 | MULADD(at[10], at[23]); MULADD(at[11], at[22]); 104 | COMBA_STORE(C->dp[21]); 105 | /* 22 */ 106 | COMBA_FORWARD; 107 | MULADD(at[11], at[23]); 108 | COMBA_STORE(C->dp[22]); 109 | COMBA_STORE2(C->dp[23]); 110 | C->used = 24; 111 | C->sign = A->sign ^ B->sign; 112 | fp_clamp(C); 113 | COMBA_FINI; 114 | } 115 | #endif 116 | -------------------------------------------------------------------------------- /src/mul/fp_mul_comba_3.c: -------------------------------------------------------------------------------- 1 | /* TomsFastMath, a fast ISO C bignum library. -- Tom St Denis */ 2 | /* SPDX-License-Identifier: Unlicense */ 3 | #ifndef TFM_PRE_GEN_MPI_C 4 | #define TFM_DEFINES 5 | #include "fp_mul_comba.c" 6 | #endif 7 | 8 | #if defined(TFM_MUL3) && FP_SIZE >= 6 9 | void fp_mul_comba3(const fp_int *A, const fp_int *B, fp_int *C) 10 | { 11 | fp_digit c0, c1, c2, at[6]; 12 | 13 | memcpy(at, A->dp, 3 * sizeof(fp_digit)); 14 | memcpy(at+3, B->dp, 3 * sizeof(fp_digit)); 15 | COMBA_START; 16 | 17 | COMBA_CLEAR; 18 | /* 0 */ 19 | MULADD(at[0], at[3]); 20 | COMBA_STORE(C->dp[0]); 21 | /* 1 */ 22 | COMBA_FORWARD; 23 | MULADD(at[0], at[4]); MULADD(at[1], at[3]); 24 | COMBA_STORE(C->dp[1]); 25 | /* 2 */ 26 | COMBA_FORWARD; 27 | MULADD(at[0], at[5]); MULADD(at[1], at[4]); MULADD(at[2], at[3]); 28 | COMBA_STORE(C->dp[2]); 29 | /* 3 */ 30 | COMBA_FORWARD; 31 | MULADD(at[1], at[5]); MULADD(at[2], at[4]); 32 | COMBA_STORE(C->dp[3]); 33 | /* 4 */ 34 | COMBA_FORWARD; 35 | MULADD(at[2], at[5]); 36 | COMBA_STORE(C->dp[4]); 37 | COMBA_STORE2(C->dp[5]); 38 | C->used = 6; 39 | C->sign = A->sign ^ B->sign; 40 | fp_clamp(C); 41 | COMBA_FINI; 42 | } 43 | #endif 44 | -------------------------------------------------------------------------------- /src/mul/fp_mul_comba_4.c: -------------------------------------------------------------------------------- 1 | /* TomsFastMath, a fast ISO C bignum library. -- Tom St Denis */ 2 | /* SPDX-License-Identifier: Unlicense */ 3 | #ifndef TFM_PRE_GEN_MPI_C 4 | #define TFM_DEFINES 5 | #include "fp_mul_comba.c" 6 | #endif 7 | 8 | #if defined(TFM_MUL4) && FP_SIZE >= 8 9 | void fp_mul_comba4(const fp_int *A, const fp_int *B, fp_int *C) 10 | { 11 | fp_digit c0, c1, c2, at[8]; 12 | 13 | memcpy(at, A->dp, 4 * sizeof(fp_digit)); 14 | memcpy(at+4, B->dp, 4 * sizeof(fp_digit)); 15 | COMBA_START; 16 | 17 | COMBA_CLEAR; 18 | /* 0 */ 19 | MULADD(at[0], at[4]); 20 | COMBA_STORE(C->dp[0]); 21 | /* 1 */ 22 | COMBA_FORWARD; 23 | MULADD(at[0], at[5]); MULADD(at[1], at[4]); 24 | COMBA_STORE(C->dp[1]); 25 | /* 2 */ 26 | COMBA_FORWARD; 27 | MULADD(at[0], at[6]); MULADD(at[1], at[5]); MULADD(at[2], at[4]); 28 | COMBA_STORE(C->dp[2]); 29 | /* 3 */ 30 | COMBA_FORWARD; 31 | MULADD(at[0], at[7]); MULADD(at[1], at[6]); MULADD(at[2], at[5]); MULADD(at[3], at[4]); 32 | COMBA_STORE(C->dp[3]); 33 | /* 4 */ 34 | COMBA_FORWARD; 35 | MULADD(at[1], at[7]); MULADD(at[2], at[6]); MULADD(at[3], at[5]); 36 | COMBA_STORE(C->dp[4]); 37 | /* 5 */ 38 | COMBA_FORWARD; 39 | MULADD(at[2], at[7]); MULADD(at[3], at[6]); 40 | COMBA_STORE(C->dp[5]); 41 | /* 6 */ 42 | COMBA_FORWARD; 43 | MULADD(at[3], at[7]); 44 | COMBA_STORE(C->dp[6]); 45 | COMBA_STORE2(C->dp[7]); 46 | C->used = 8; 47 | C->sign = A->sign ^ B->sign; 48 | fp_clamp(C); 49 | COMBA_FINI; 50 | } 51 | #endif 52 | -------------------------------------------------------------------------------- /src/mul/fp_mul_comba_6.c: -------------------------------------------------------------------------------- 1 | /* TomsFastMath, a fast ISO C bignum library. -- Tom St Denis */ 2 | /* SPDX-License-Identifier: Unlicense */ 3 | #ifndef TFM_PRE_GEN_MPI_C 4 | #define TFM_DEFINES 5 | #include "fp_mul_comba.c" 6 | #endif 7 | 8 | #if defined(TFM_MUL6) && FP_SIZE >= 12 9 | void fp_mul_comba6(const fp_int *A, const fp_int *B, fp_int *C) 10 | { 11 | fp_digit c0, c1, c2, at[12]; 12 | 13 | memcpy(at, A->dp, 6 * sizeof(fp_digit)); 14 | memcpy(at+6, B->dp, 6 * sizeof(fp_digit)); 15 | COMBA_START; 16 | 17 | COMBA_CLEAR; 18 | /* 0 */ 19 | MULADD(at[0], at[6]); 20 | COMBA_STORE(C->dp[0]); 21 | /* 1 */ 22 | COMBA_FORWARD; 23 | MULADD(at[0], at[7]); MULADD(at[1], at[6]); 24 | COMBA_STORE(C->dp[1]); 25 | /* 2 */ 26 | COMBA_FORWARD; 27 | MULADD(at[0], at[8]); MULADD(at[1], at[7]); MULADD(at[2], at[6]); 28 | COMBA_STORE(C->dp[2]); 29 | /* 3 */ 30 | COMBA_FORWARD; 31 | MULADD(at[0], at[9]); MULADD(at[1], at[8]); MULADD(at[2], at[7]); MULADD(at[3], at[6]); 32 | COMBA_STORE(C->dp[3]); 33 | /* 4 */ 34 | COMBA_FORWARD; 35 | MULADD(at[0], at[10]); MULADD(at[1], at[9]); MULADD(at[2], at[8]); MULADD(at[3], at[7]); MULADD(at[4], at[6]); 36 | COMBA_STORE(C->dp[4]); 37 | /* 5 */ 38 | COMBA_FORWARD; 39 | MULADD(at[0], at[11]); MULADD(at[1], at[10]); MULADD(at[2], at[9]); MULADD(at[3], at[8]); MULADD(at[4], at[7]); MULADD(at[5], at[6]); 40 | COMBA_STORE(C->dp[5]); 41 | /* 6 */ 42 | COMBA_FORWARD; 43 | MULADD(at[1], at[11]); MULADD(at[2], at[10]); MULADD(at[3], at[9]); MULADD(at[4], at[8]); MULADD(at[5], at[7]); 44 | COMBA_STORE(C->dp[6]); 45 | /* 7 */ 46 | COMBA_FORWARD; 47 | MULADD(at[2], at[11]); MULADD(at[3], at[10]); MULADD(at[4], at[9]); MULADD(at[5], at[8]); 48 | COMBA_STORE(C->dp[7]); 49 | /* 8 */ 50 | COMBA_FORWARD; 51 | MULADD(at[3], at[11]); MULADD(at[4], at[10]); MULADD(at[5], at[9]); 52 | COMBA_STORE(C->dp[8]); 53 | /* 9 */ 54 | COMBA_FORWARD; 55 | MULADD(at[4], at[11]); MULADD(at[5], at[10]); 56 | COMBA_STORE(C->dp[9]); 57 | /* 10 */ 58 | COMBA_FORWARD; 59 | MULADD(at[5], at[11]); 60 | COMBA_STORE(C->dp[10]); 61 | COMBA_STORE2(C->dp[11]); 62 | C->used = 12; 63 | C->sign = A->sign ^ B->sign; 64 | fp_clamp(C); 65 | COMBA_FINI; 66 | } 67 | #endif 68 | -------------------------------------------------------------------------------- /src/mul/fp_mul_comba_7.c: -------------------------------------------------------------------------------- 1 | /* TomsFastMath, a fast ISO C bignum library. -- Tom St Denis */ 2 | /* SPDX-License-Identifier: Unlicense */ 3 | #ifndef TFM_PRE_GEN_MPI_C 4 | #define TFM_DEFINES 5 | #include "fp_mul_comba.c" 6 | #endif 7 | 8 | #if defined(TFM_MUL7) && FP_SIZE >= 14 9 | void fp_mul_comba7(const fp_int *A, const fp_int *B, fp_int *C) 10 | { 11 | fp_digit c0, c1, c2, at[14]; 12 | 13 | memcpy(at, A->dp, 7 * sizeof(fp_digit)); 14 | memcpy(at+7, B->dp, 7 * sizeof(fp_digit)); 15 | COMBA_START; 16 | 17 | COMBA_CLEAR; 18 | /* 0 */ 19 | MULADD(at[0], at[7]); 20 | COMBA_STORE(C->dp[0]); 21 | /* 1 */ 22 | COMBA_FORWARD; 23 | MULADD(at[0], at[8]); MULADD(at[1], at[7]); 24 | COMBA_STORE(C->dp[1]); 25 | /* 2 */ 26 | COMBA_FORWARD; 27 | MULADD(at[0], at[9]); MULADD(at[1], at[8]); MULADD(at[2], at[7]); 28 | COMBA_STORE(C->dp[2]); 29 | /* 3 */ 30 | COMBA_FORWARD; 31 | MULADD(at[0], at[10]); MULADD(at[1], at[9]); MULADD(at[2], at[8]); MULADD(at[3], at[7]); 32 | COMBA_STORE(C->dp[3]); 33 | /* 4 */ 34 | COMBA_FORWARD; 35 | MULADD(at[0], at[11]); MULADD(at[1], at[10]); MULADD(at[2], at[9]); MULADD(at[3], at[8]); MULADD(at[4], at[7]); 36 | COMBA_STORE(C->dp[4]); 37 | /* 5 */ 38 | COMBA_FORWARD; 39 | MULADD(at[0], at[12]); MULADD(at[1], at[11]); MULADD(at[2], at[10]); MULADD(at[3], at[9]); MULADD(at[4], at[8]); MULADD(at[5], at[7]); 40 | COMBA_STORE(C->dp[5]); 41 | /* 6 */ 42 | COMBA_FORWARD; 43 | MULADD(at[0], at[13]); MULADD(at[1], at[12]); MULADD(at[2], at[11]); MULADD(at[3], at[10]); MULADD(at[4], at[9]); MULADD(at[5], at[8]); MULADD(at[6], at[7]); 44 | COMBA_STORE(C->dp[6]); 45 | /* 7 */ 46 | COMBA_FORWARD; 47 | MULADD(at[1], at[13]); MULADD(at[2], at[12]); MULADD(at[3], at[11]); MULADD(at[4], at[10]); MULADD(at[5], at[9]); MULADD(at[6], at[8]); 48 | COMBA_STORE(C->dp[7]); 49 | /* 8 */ 50 | COMBA_FORWARD; 51 | MULADD(at[2], at[13]); MULADD(at[3], at[12]); MULADD(at[4], at[11]); MULADD(at[5], at[10]); MULADD(at[6], at[9]); 52 | COMBA_STORE(C->dp[8]); 53 | /* 9 */ 54 | COMBA_FORWARD; 55 | MULADD(at[3], at[13]); MULADD(at[4], at[12]); MULADD(at[5], at[11]); MULADD(at[6], at[10]); 56 | COMBA_STORE(C->dp[9]); 57 | /* 10 */ 58 | COMBA_FORWARD; 59 | MULADD(at[4], at[13]); MULADD(at[5], at[12]); MULADD(at[6], at[11]); 60 | COMBA_STORE(C->dp[10]); 61 | /* 11 */ 62 | COMBA_FORWARD; 63 | MULADD(at[5], at[13]); MULADD(at[6], at[12]); 64 | COMBA_STORE(C->dp[11]); 65 | /* 12 */ 66 | COMBA_FORWARD; 67 | MULADD(at[6], at[13]); 68 | COMBA_STORE(C->dp[12]); 69 | COMBA_STORE2(C->dp[13]); 70 | C->used = 14; 71 | C->sign = A->sign ^ B->sign; 72 | fp_clamp(C); 73 | COMBA_FINI; 74 | } 75 | #endif 76 | -------------------------------------------------------------------------------- /src/mul/fp_mul_comba_8.c: -------------------------------------------------------------------------------- 1 | /* TomsFastMath, a fast ISO C bignum library. -- Tom St Denis */ 2 | /* SPDX-License-Identifier: Unlicense */ 3 | #ifndef TFM_PRE_GEN_MPI_C 4 | #define TFM_DEFINES 5 | #include "fp_mul_comba.c" 6 | #endif 7 | 8 | #if defined(TFM_MUL8) && FP_SIZE >= 16 9 | void fp_mul_comba8(const fp_int *A, const fp_int *B, fp_int *C) 10 | { 11 | fp_digit c0, c1, c2, at[16]; 12 | 13 | memcpy(at, A->dp, 8 * sizeof(fp_digit)); 14 | memcpy(at+8, B->dp, 8 * sizeof(fp_digit)); 15 | COMBA_START; 16 | 17 | COMBA_CLEAR; 18 | /* 0 */ 19 | MULADD(at[0], at[8]); 20 | COMBA_STORE(C->dp[0]); 21 | /* 1 */ 22 | COMBA_FORWARD; 23 | MULADD(at[0], at[9]); MULADD(at[1], at[8]); 24 | COMBA_STORE(C->dp[1]); 25 | /* 2 */ 26 | COMBA_FORWARD; 27 | MULADD(at[0], at[10]); MULADD(at[1], at[9]); MULADD(at[2], at[8]); 28 | COMBA_STORE(C->dp[2]); 29 | /* 3 */ 30 | COMBA_FORWARD; 31 | MULADD(at[0], at[11]); MULADD(at[1], at[10]); MULADD(at[2], at[9]); MULADD(at[3], at[8]); 32 | COMBA_STORE(C->dp[3]); 33 | /* 4 */ 34 | COMBA_FORWARD; 35 | MULADD(at[0], at[12]); MULADD(at[1], at[11]); MULADD(at[2], at[10]); MULADD(at[3], at[9]); MULADD(at[4], at[8]); 36 | COMBA_STORE(C->dp[4]); 37 | /* 5 */ 38 | COMBA_FORWARD; 39 | MULADD(at[0], at[13]); MULADD(at[1], at[12]); MULADD(at[2], at[11]); MULADD(at[3], at[10]); MULADD(at[4], at[9]); MULADD(at[5], at[8]); 40 | COMBA_STORE(C->dp[5]); 41 | /* 6 */ 42 | COMBA_FORWARD; 43 | MULADD(at[0], at[14]); MULADD(at[1], at[13]); MULADD(at[2], at[12]); MULADD(at[3], at[11]); MULADD(at[4], at[10]); MULADD(at[5], at[9]); MULADD(at[6], at[8]); 44 | COMBA_STORE(C->dp[6]); 45 | /* 7 */ 46 | COMBA_FORWARD; 47 | MULADD(at[0], at[15]); MULADD(at[1], at[14]); MULADD(at[2], at[13]); MULADD(at[3], at[12]); MULADD(at[4], at[11]); MULADD(at[5], at[10]); MULADD(at[6], at[9]); MULADD(at[7], at[8]); 48 | COMBA_STORE(C->dp[7]); 49 | /* 8 */ 50 | COMBA_FORWARD; 51 | MULADD(at[1], at[15]); MULADD(at[2], at[14]); MULADD(at[3], at[13]); MULADD(at[4], at[12]); MULADD(at[5], at[11]); MULADD(at[6], at[10]); MULADD(at[7], at[9]); 52 | COMBA_STORE(C->dp[8]); 53 | /* 9 */ 54 | COMBA_FORWARD; 55 | MULADD(at[2], at[15]); MULADD(at[3], at[14]); MULADD(at[4], at[13]); MULADD(at[5], at[12]); MULADD(at[6], at[11]); MULADD(at[7], at[10]); 56 | COMBA_STORE(C->dp[9]); 57 | /* 10 */ 58 | COMBA_FORWARD; 59 | MULADD(at[3], at[15]); MULADD(at[4], at[14]); MULADD(at[5], at[13]); MULADD(at[6], at[12]); MULADD(at[7], at[11]); 60 | COMBA_STORE(C->dp[10]); 61 | /* 11 */ 62 | COMBA_FORWARD; 63 | MULADD(at[4], at[15]); MULADD(at[5], at[14]); MULADD(at[6], at[13]); MULADD(at[7], at[12]); 64 | COMBA_STORE(C->dp[11]); 65 | /* 12 */ 66 | COMBA_FORWARD; 67 | MULADD(at[5], at[15]); MULADD(at[6], at[14]); MULADD(at[7], at[13]); 68 | COMBA_STORE(C->dp[12]); 69 | /* 13 */ 70 | COMBA_FORWARD; 71 | MULADD(at[6], at[15]); MULADD(at[7], at[14]); 72 | COMBA_STORE(C->dp[13]); 73 | /* 14 */ 74 | COMBA_FORWARD; 75 | MULADD(at[7], at[15]); 76 | COMBA_STORE(C->dp[14]); 77 | COMBA_STORE2(C->dp[15]); 78 | C->used = 16; 79 | C->sign = A->sign ^ B->sign; 80 | fp_clamp(C); 81 | COMBA_FINI; 82 | } 83 | #endif 84 | -------------------------------------------------------------------------------- /src/mul/fp_mul_comba_9.c: -------------------------------------------------------------------------------- 1 | /* TomsFastMath, a fast ISO C bignum library. -- Tom St Denis */ 2 | /* SPDX-License-Identifier: Unlicense */ 3 | #ifndef TFM_PRE_GEN_MPI_C 4 | #define TFM_DEFINES 5 | #include "fp_mul_comba.c" 6 | #endif 7 | 8 | #if defined(TFM_MUL9) && FP_SIZE >= 18 9 | void fp_mul_comba9(const fp_int *A, const fp_int *B, fp_int *C) 10 | { 11 | fp_digit c0, c1, c2, at[18]; 12 | 13 | memcpy(at, A->dp, 9 * sizeof(fp_digit)); 14 | memcpy(at+9, B->dp, 9 * sizeof(fp_digit)); 15 | COMBA_START; 16 | 17 | COMBA_CLEAR; 18 | /* 0 */ 19 | MULADD(at[0], at[9]); 20 | COMBA_STORE(C->dp[0]); 21 | /* 1 */ 22 | COMBA_FORWARD; 23 | MULADD(at[0], at[10]); MULADD(at[1], at[9]); 24 | COMBA_STORE(C->dp[1]); 25 | /* 2 */ 26 | COMBA_FORWARD; 27 | MULADD(at[0], at[11]); MULADD(at[1], at[10]); MULADD(at[2], at[9]); 28 | COMBA_STORE(C->dp[2]); 29 | /* 3 */ 30 | COMBA_FORWARD; 31 | MULADD(at[0], at[12]); MULADD(at[1], at[11]); MULADD(at[2], at[10]); MULADD(at[3], at[9]); 32 | COMBA_STORE(C->dp[3]); 33 | /* 4 */ 34 | COMBA_FORWARD; 35 | MULADD(at[0], at[13]); MULADD(at[1], at[12]); MULADD(at[2], at[11]); MULADD(at[3], at[10]); MULADD(at[4], at[9]); 36 | COMBA_STORE(C->dp[4]); 37 | /* 5 */ 38 | COMBA_FORWARD; 39 | MULADD(at[0], at[14]); MULADD(at[1], at[13]); MULADD(at[2], at[12]); MULADD(at[3], at[11]); MULADD(at[4], at[10]); MULADD(at[5], at[9]); 40 | COMBA_STORE(C->dp[5]); 41 | /* 6 */ 42 | COMBA_FORWARD; 43 | MULADD(at[0], at[15]); MULADD(at[1], at[14]); MULADD(at[2], at[13]); MULADD(at[3], at[12]); MULADD(at[4], at[11]); MULADD(at[5], at[10]); MULADD(at[6], at[9]); 44 | COMBA_STORE(C->dp[6]); 45 | /* 7 */ 46 | COMBA_FORWARD; 47 | MULADD(at[0], at[16]); MULADD(at[1], at[15]); MULADD(at[2], at[14]); MULADD(at[3], at[13]); MULADD(at[4], at[12]); MULADD(at[5], at[11]); MULADD(at[6], at[10]); MULADD(at[7], at[9]); 48 | COMBA_STORE(C->dp[7]); 49 | /* 8 */ 50 | COMBA_FORWARD; 51 | MULADD(at[0], at[17]); MULADD(at[1], at[16]); MULADD(at[2], at[15]); MULADD(at[3], at[14]); MULADD(at[4], at[13]); MULADD(at[5], at[12]); MULADD(at[6], at[11]); MULADD(at[7], at[10]); MULADD(at[8], at[9]); 52 | COMBA_STORE(C->dp[8]); 53 | /* 9 */ 54 | COMBA_FORWARD; 55 | MULADD(at[1], at[17]); MULADD(at[2], at[16]); MULADD(at[3], at[15]); MULADD(at[4], at[14]); MULADD(at[5], at[13]); MULADD(at[6], at[12]); MULADD(at[7], at[11]); MULADD(at[8], at[10]); 56 | COMBA_STORE(C->dp[9]); 57 | /* 10 */ 58 | COMBA_FORWARD; 59 | MULADD(at[2], at[17]); MULADD(at[3], at[16]); MULADD(at[4], at[15]); MULADD(at[5], at[14]); MULADD(at[6], at[13]); MULADD(at[7], at[12]); MULADD(at[8], at[11]); 60 | COMBA_STORE(C->dp[10]); 61 | /* 11 */ 62 | COMBA_FORWARD; 63 | MULADD(at[3], at[17]); MULADD(at[4], at[16]); MULADD(at[5], at[15]); MULADD(at[6], at[14]); MULADD(at[7], at[13]); MULADD(at[8], at[12]); 64 | COMBA_STORE(C->dp[11]); 65 | /* 12 */ 66 | COMBA_FORWARD; 67 | MULADD(at[4], at[17]); MULADD(at[5], at[16]); MULADD(at[6], at[15]); MULADD(at[7], at[14]); MULADD(at[8], at[13]); 68 | COMBA_STORE(C->dp[12]); 69 | /* 13 */ 70 | COMBA_FORWARD; 71 | MULADD(at[5], at[17]); MULADD(at[6], at[16]); MULADD(at[7], at[15]); MULADD(at[8], at[14]); 72 | COMBA_STORE(C->dp[13]); 73 | /* 14 */ 74 | COMBA_FORWARD; 75 | MULADD(at[6], at[17]); MULADD(at[7], at[16]); MULADD(at[8], at[15]); 76 | COMBA_STORE(C->dp[14]); 77 | /* 15 */ 78 | COMBA_FORWARD; 79 | MULADD(at[7], at[17]); MULADD(at[8], at[16]); 80 | COMBA_STORE(C->dp[15]); 81 | /* 16 */ 82 | COMBA_FORWARD; 83 | MULADD(at[8], at[17]); 84 | COMBA_STORE(C->dp[16]); 85 | COMBA_STORE2(C->dp[17]); 86 | C->used = 18; 87 | C->sign = A->sign ^ B->sign; 88 | fp_clamp(C); 89 | COMBA_FINI; 90 | } 91 | #endif 92 | -------------------------------------------------------------------------------- /src/mul/fp_mul_d.c: -------------------------------------------------------------------------------- 1 | /* TomsFastMath, a fast ISO C bignum library. -- Tom St Denis */ 2 | /* SPDX-License-Identifier: Unlicense */ 3 | #include 4 | 5 | /* c = a * b */ 6 | void fp_mul_d(const fp_int *a, fp_digit b, fp_int *c) 7 | { 8 | fp_word w; 9 | int x, oldused; 10 | 11 | oldused = c->used; 12 | c->used = a->used; 13 | c->sign = a->sign; 14 | w = 0; 15 | for (x = 0; x < a->used; x++) { 16 | w = ((fp_word)a->dp[x]) * ((fp_word)b) + w; 17 | c->dp[x] = (fp_digit)w; 18 | w = w >> DIGIT_BIT; 19 | } 20 | if (w != 0 && (a->used != FP_SIZE)) { 21 | c->dp[c->used++] = w; 22 | ++x; 23 | } 24 | for (; x < oldused; x++) { 25 | c->dp[x] = 0; 26 | } 27 | fp_clamp(c); 28 | } 29 | -------------------------------------------------------------------------------- /src/mul/fp_mulmod.c: -------------------------------------------------------------------------------- 1 | /* TomsFastMath, a fast ISO C bignum library. -- Tom St Denis */ 2 | /* SPDX-License-Identifier: Unlicense */ 3 | #include 4 | /* d = a * b (mod c) */ 5 | int fp_mulmod(const fp_int *a, const fp_int *b, const fp_int *c, fp_int *d) 6 | { 7 | fp_int tmp; 8 | fp_zero(&tmp); 9 | fp_mul(a, b, &tmp); 10 | return fp_mod(&tmp, c, d); 11 | } 12 | -------------------------------------------------------------------------------- /src/numtheory/fp_gcd.c: -------------------------------------------------------------------------------- 1 | /* TomsFastMath, a fast ISO C bignum library. -- Tom St Denis */ 2 | /* SPDX-License-Identifier: Unlicense */ 3 | #include 4 | 5 | /* c = (a, b) */ 6 | void fp_gcd(const fp_int *a, const fp_int *b, fp_int *c) 7 | { 8 | fp_int u, v, r; 9 | 10 | /* either zero than gcd is the largest */ 11 | if (fp_iszero (a) == 1 && fp_iszero (b) == 0) { 12 | fp_abs (b, c); 13 | return; 14 | } 15 | if (fp_iszero (a) == 0 && fp_iszero (b) == 1) { 16 | fp_abs (a, c); 17 | return; 18 | } 19 | 20 | /* optimized. At this point if a == 0 then 21 | * b must equal zero too 22 | */ 23 | if (fp_iszero (a) == 1) { 24 | fp_zero(c); 25 | return; 26 | } 27 | 28 | /* sort inputs */ 29 | if (fp_cmp_mag(a, b) != FP_LT) { 30 | fp_init_copy(&u, a); 31 | fp_init_copy(&v, b); 32 | } else { 33 | fp_init_copy(&u, b); 34 | fp_init_copy(&v, a); 35 | } 36 | 37 | fp_zero(&r); 38 | while (fp_iszero(&v) == FP_NO) { 39 | fp_mod(&u, &v, &r); 40 | fp_copy(&v, &u); 41 | fp_copy(&r, &v); 42 | } 43 | fp_copy(&u, c); 44 | } 45 | -------------------------------------------------------------------------------- /src/numtheory/fp_invmod.c: -------------------------------------------------------------------------------- 1 | /* TomsFastMath, a fast ISO C bignum library. -- Tom St Denis */ 2 | /* SPDX-License-Identifier: Unlicense */ 3 | #include 4 | 5 | static int s_fp_invmod_slow (const fp_int * a, const fp_int * b, fp_int * c) 6 | { 7 | fp_int x, y, u, v, A, B, C, D; 8 | int res; 9 | 10 | /* b cannot be negative */ 11 | if (b->sign == FP_NEG || fp_iszero(b) == 1) { 12 | return FP_VAL; 13 | } 14 | 15 | /* init temps */ 16 | fp_init(&x); fp_init(&y); 17 | fp_init(&u); fp_init(&v); 18 | fp_init(&A); fp_init(&B); 19 | fp_init(&C); fp_init(&D); 20 | 21 | /* x = a, y = b */ 22 | if ((res = fp_mod(a, b, &x)) != FP_OKAY) { 23 | return res; 24 | } 25 | fp_copy(b, &y); 26 | 27 | /* 2. [modified] if x,y are both even then return an error! */ 28 | if (fp_iseven (&x) == 1 && fp_iseven (&y) == 1) { 29 | return FP_VAL; 30 | } 31 | 32 | /* 3. u=x, v=y, A=1, B=0, C=0,D=1 */ 33 | fp_copy (&x, &u); 34 | fp_copy (&y, &v); 35 | fp_set (&A, 1); 36 | fp_set (&D, 1); 37 | 38 | top: 39 | /* 4. while u is even do */ 40 | while (fp_iseven (&u) == 1) { 41 | /* 4.1 u = u/2 */ 42 | fp_div_2 (&u, &u); 43 | 44 | /* 4.2 if A or B is odd then */ 45 | if (fp_isodd (&A) == 1 || fp_isodd (&B) == 1) { 46 | /* A = (A+y)/2, B = (B-x)/2 */ 47 | fp_add (&A, &y, &A); 48 | fp_sub (&B, &x, &B); 49 | } 50 | /* A = A/2, B = B/2 */ 51 | fp_div_2 (&A, &A); 52 | fp_div_2 (&B, &B); 53 | } 54 | 55 | /* 5. while v is even do */ 56 | while (fp_iseven (&v) == 1) { 57 | /* 5.1 v = v/2 */ 58 | fp_div_2 (&v, &v); 59 | 60 | /* 5.2 if C or D is odd then */ 61 | if (fp_isodd (&C) == 1 || fp_isodd (&D) == 1) { 62 | /* C = (C+y)/2, D = (D-x)/2 */ 63 | fp_add (&C, &y, &C); 64 | fp_sub (&D, &x, &D); 65 | } 66 | /* C = C/2, D = D/2 */ 67 | fp_div_2 (&C, &C); 68 | fp_div_2 (&D, &D); 69 | } 70 | 71 | /* 6. if u >= v then */ 72 | if (fp_cmp (&u, &v) != FP_LT) { 73 | /* u = u - v, A = A - C, B = B - D */ 74 | fp_sub (&u, &v, &u); 75 | fp_sub (&A, &C, &A); 76 | fp_sub (&B, &D, &B); 77 | } else { 78 | /* v - v - u, C = C - A, D = D - B */ 79 | fp_sub (&v, &u, &v); 80 | fp_sub (&C, &A, &C); 81 | fp_sub (&D, &B, &D); 82 | } 83 | 84 | /* if not zero goto step 4 */ 85 | if (fp_iszero (&u) == 0) 86 | goto top; 87 | 88 | /* now a = C, b = D, gcd == g*v */ 89 | 90 | /* if v != 1 then there is no inverse */ 91 | if (fp_cmp_d (&v, 1) != FP_EQ) { 92 | return FP_VAL; 93 | } 94 | 95 | /* if its too low */ 96 | while (fp_cmp_d(&C, 0) == FP_LT) { 97 | fp_add(&C, b, &C); 98 | } 99 | 100 | /* too big */ 101 | while (fp_cmp_mag(&C, b) != FP_LT) { 102 | fp_sub(&C, b, &C); 103 | } 104 | 105 | /* C is now the inverse */ 106 | fp_copy(&C, c); 107 | return FP_OKAY; 108 | } 109 | 110 | /* c = 1/a (mod b) for odd b only */ 111 | int fp_invmod(const fp_int *a, const fp_int *b, fp_int *c) 112 | { 113 | fp_int x, y, u, v, B, D; 114 | int neg; 115 | 116 | /* 2. [modified] b must be odd */ 117 | if (fp_iseven (b) == FP_YES) { 118 | return s_fp_invmod_slow(a,b,c); 119 | } 120 | 121 | /* init all our temps */ 122 | fp_init(&x); fp_init(&y); 123 | fp_init(&u); fp_init(&v); 124 | fp_init(&B); fp_init(&D); 125 | 126 | /* x == modulus, y == value to invert */ 127 | fp_copy(b, &x); 128 | 129 | /* we need y = |a| */ 130 | fp_abs(a, &y); 131 | 132 | /* 3. u=x, v=y, A=1, B=0, C=0,D=1 */ 133 | fp_copy(&x, &u); 134 | fp_copy(&y, &v); 135 | fp_set (&D, 1); 136 | 137 | top: 138 | /* 4. while u is even do */ 139 | while (fp_iseven (&u) == FP_YES) { 140 | /* 4.1 u = u/2 */ 141 | fp_div_2 (&u, &u); 142 | 143 | /* 4.2 if B is odd then */ 144 | if (fp_isodd (&B) == FP_YES) { 145 | fp_sub (&B, &x, &B); 146 | } 147 | /* B = B/2 */ 148 | fp_div_2 (&B, &B); 149 | } 150 | 151 | /* 5. while v is even do */ 152 | while (fp_iseven (&v) == FP_YES) { 153 | /* 5.1 v = v/2 */ 154 | fp_div_2 (&v, &v); 155 | 156 | /* 5.2 if D is odd then */ 157 | if (fp_isodd (&D) == FP_YES) { 158 | /* D = (D-x)/2 */ 159 | fp_sub (&D, &x, &D); 160 | } 161 | /* D = D/2 */ 162 | fp_div_2 (&D, &D); 163 | } 164 | 165 | /* 6. if u >= v then */ 166 | if (fp_cmp (&u, &v) != FP_LT) { 167 | /* u = u - v, B = B - D */ 168 | fp_sub (&u, &v, &u); 169 | fp_sub (&B, &D, &B); 170 | } else { 171 | /* v - v - u, D = D - B */ 172 | fp_sub (&v, &u, &v); 173 | fp_sub (&D, &B, &D); 174 | } 175 | 176 | /* if not zero goto step 4 */ 177 | if (fp_iszero (&u) == FP_NO) { 178 | goto top; 179 | } 180 | 181 | /* now a = C, b = D, gcd == g*v */ 182 | 183 | /* if v != 1 then there is no inverse */ 184 | if (fp_cmp_d (&v, 1) != FP_EQ) { 185 | return FP_VAL; 186 | } 187 | 188 | /* b is now the inverse */ 189 | neg = a->sign; 190 | while (D.sign == FP_NEG) { 191 | fp_add (&D, b, &D); 192 | } 193 | fp_copy (&D, c); 194 | c->sign = neg; 195 | return FP_OKAY; 196 | } 197 | -------------------------------------------------------------------------------- /src/numtheory/fp_isprime.c: -------------------------------------------------------------------------------- 1 | /* TomsFastMath, a fast ISO C bignum library. -- Tom St Denis */ 2 | /* SPDX-License-Identifier: Unlicense */ 3 | #include 4 | 5 | int fp_isprime(const fp_int *a) 6 | { 7 | return fp_isprime_ex(a, 8); 8 | } 9 | -------------------------------------------------------------------------------- /src/numtheory/fp_isprime_ex.c: -------------------------------------------------------------------------------- 1 | /* TomsFastMath, a fast ISO C bignum library. -- Tom St Denis */ 2 | /* SPDX-License-Identifier: Unlicense */ 3 | #include 4 | 5 | /* a few primes */ 6 | static const fp_digit primes[FP_PRIME_SIZE] = { 7 | 0x0002, 0x0003, 0x0005, 0x0007, 0x000B, 0x000D, 0x0011, 0x0013, 8 | 0x0017, 0x001D, 0x001F, 0x0025, 0x0029, 0x002B, 0x002F, 0x0035, 9 | 0x003B, 0x003D, 0x0043, 0x0047, 0x0049, 0x004F, 0x0053, 0x0059, 10 | 0x0061, 0x0065, 0x0067, 0x006B, 0x006D, 0x0071, 0x007F, 0x0083, 11 | 0x0089, 0x008B, 0x0095, 0x0097, 0x009D, 0x00A3, 0x00A7, 0x00AD, 12 | 0x00B3, 0x00B5, 0x00BF, 0x00C1, 0x00C5, 0x00C7, 0x00D3, 0x00DF, 13 | 0x00E3, 0x00E5, 0x00E9, 0x00EF, 0x00F1, 0x00FB, 0x0101, 0x0107, 14 | 0x010D, 0x010F, 0x0115, 0x0119, 0x011B, 0x0125, 0x0133, 0x0137, 15 | 16 | 0x0139, 0x013D, 0x014B, 0x0151, 0x015B, 0x015D, 0x0161, 0x0167, 17 | 0x016F, 0x0175, 0x017B, 0x017F, 0x0185, 0x018D, 0x0191, 0x0199, 18 | 0x01A3, 0x01A5, 0x01AF, 0x01B1, 0x01B7, 0x01BB, 0x01C1, 0x01C9, 19 | 0x01CD, 0x01CF, 0x01D3, 0x01DF, 0x01E7, 0x01EB, 0x01F3, 0x01F7, 20 | 0x01FD, 0x0209, 0x020B, 0x021D, 0x0223, 0x022D, 0x0233, 0x0239, 21 | 0x023B, 0x0241, 0x024B, 0x0251, 0x0257, 0x0259, 0x025F, 0x0265, 22 | 0x0269, 0x026B, 0x0277, 0x0281, 0x0283, 0x0287, 0x028D, 0x0293, 23 | 0x0295, 0x02A1, 0x02A5, 0x02AB, 0x02B3, 0x02BD, 0x02C5, 0x02CF, 24 | 25 | 0x02D7, 0x02DD, 0x02E3, 0x02E7, 0x02EF, 0x02F5, 0x02F9, 0x0301, 26 | 0x0305, 0x0313, 0x031D, 0x0329, 0x032B, 0x0335, 0x0337, 0x033B, 27 | 0x033D, 0x0347, 0x0355, 0x0359, 0x035B, 0x035F, 0x036D, 0x0371, 28 | 0x0373, 0x0377, 0x038B, 0x038F, 0x0397, 0x03A1, 0x03A9, 0x03AD, 29 | 0x03B3, 0x03B9, 0x03C7, 0x03CB, 0x03D1, 0x03D7, 0x03DF, 0x03E5, 30 | 0x03F1, 0x03F5, 0x03FB, 0x03FD, 0x0407, 0x0409, 0x040F, 0x0419, 31 | 0x041B, 0x0425, 0x0427, 0x042D, 0x043F, 0x0443, 0x0445, 0x0449, 32 | 0x044F, 0x0455, 0x045D, 0x0463, 0x0469, 0x047F, 0x0481, 0x048B, 33 | 34 | 0x0493, 0x049D, 0x04A3, 0x04A9, 0x04B1, 0x04BD, 0x04C1, 0x04C7, 35 | 0x04CD, 0x04CF, 0x04D5, 0x04E1, 0x04EB, 0x04FD, 0x04FF, 0x0503, 36 | 0x0509, 0x050B, 0x0511, 0x0515, 0x0517, 0x051B, 0x0527, 0x0529, 37 | 0x052F, 0x0551, 0x0557, 0x055D, 0x0565, 0x0577, 0x0581, 0x058F, 38 | 0x0593, 0x0595, 0x0599, 0x059F, 0x05A7, 0x05AB, 0x05AD, 0x05B3, 39 | 0x05BF, 0x05C9, 0x05CB, 0x05CF, 0x05D1, 0x05D5, 0x05DB, 0x05E7, 40 | 0x05F3, 0x05FB, 0x0607, 0x060D, 0x0611, 0x0617, 0x061F, 0x0623, 41 | 0x062B, 0x062F, 0x063D, 0x0641, 0x0647, 0x0649, 0x064D, 0x0653 42 | }; 43 | 44 | int fp_isprime_ex(const fp_int *a, int t) 45 | { 46 | fp_int b; 47 | fp_digit d; 48 | int r, res; 49 | 50 | if (t <= 0 || t > FP_PRIME_SIZE) { 51 | return FP_NO; 52 | } 53 | 54 | /* do trial division */ 55 | for (r = 0; r < 256; r++) { 56 | fp_mod_d(a, primes[r], &d); 57 | if (d == 0) { 58 | return FP_NO; 59 | } 60 | } 61 | 62 | /* now do 't' miller rabins */ 63 | fp_init(&b); 64 | for (r = 0; r < t; r++) { 65 | fp_set(&b, primes[r]); 66 | fp_prime_miller_rabin(a, &b, &res); 67 | if (res == FP_NO) { 68 | return FP_NO; 69 | } 70 | } 71 | return FP_YES; 72 | } 73 | -------------------------------------------------------------------------------- /src/numtheory/fp_lcm.c: -------------------------------------------------------------------------------- 1 | /* TomsFastMath, a fast ISO C bignum library. -- Tom St Denis */ 2 | /* SPDX-License-Identifier: Unlicense */ 3 | #include 4 | 5 | /* c = [a, b] */ 6 | void fp_lcm(const fp_int *a, const fp_int *b, fp_int *c) 7 | { 8 | fp_int t1, t2; 9 | 10 | fp_init(&t1); 11 | fp_init(&t2); 12 | fp_gcd(a, b, &t1); 13 | if (fp_cmp_mag(a, b) == FP_GT) { 14 | fp_div(a, &t1, &t2, NULL); 15 | fp_mul(b, &t2, c); 16 | } else { 17 | fp_div(b, &t1, &t2, NULL); 18 | fp_mul(a, &t2, c); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/numtheory/fp_prime_miller_rabin.c: -------------------------------------------------------------------------------- 1 | /* TomsFastMath, a fast ISO C bignum library. -- Tom St Denis */ 2 | /* SPDX-License-Identifier: Unlicense */ 3 | #include 4 | 5 | /* Miller-Rabin test of "a" to the base of "b" as described in 6 | * HAC pp. 139 Algorithm 4.24 7 | * 8 | * Sets result to 0 if definitely composite or 1 if probably prime. 9 | * Randomly the chance of error is no more than 1/4 and often 10 | * very much lower. 11 | */ 12 | void fp_prime_miller_rabin (const fp_int * a, const fp_int * b, int *result) 13 | { 14 | fp_int n1, y, r; 15 | int s, j; 16 | 17 | /* default */ 18 | *result = FP_NO; 19 | 20 | /* ensure b > 1 */ 21 | if (fp_cmp_d(b, 1) != FP_GT) { 22 | return; 23 | } 24 | 25 | /* get n1 = a - 1 */ 26 | fp_init_copy(&n1, a); 27 | fp_sub_d(&n1, 1, &n1); 28 | 29 | /* set 2**s * r = n1 */ 30 | fp_init_copy(&r, &n1); 31 | 32 | /* count the number of least significant bits 33 | * which are zero 34 | */ 35 | s = fp_cnt_lsb(&r); 36 | 37 | /* now divide n - 1 by 2**s */ 38 | fp_div_2d (&r, s, &r, NULL); 39 | 40 | /* compute y = b**r mod a */ 41 | fp_init(&y); 42 | fp_exptmod(b, &r, a, &y); 43 | 44 | /* if y != 1 and y != n1 do */ 45 | if (fp_cmp_d (&y, 1) != FP_EQ && fp_cmp (&y, &n1) != FP_EQ) { 46 | j = 1; 47 | /* while j <= s-1 and y != n1 */ 48 | while ((j <= (s - 1)) && fp_cmp (&y, &n1) != FP_EQ) { 49 | fp_sqrmod (&y, a, &y); 50 | 51 | /* if y == 1 then composite */ 52 | if (fp_cmp_d (&y, 1) == FP_EQ) { 53 | return; 54 | } 55 | ++j; 56 | } 57 | 58 | /* if y != n1 then composite */ 59 | if (fp_cmp (&y, &n1) != FP_EQ) { 60 | return; 61 | } 62 | } 63 | 64 | /* probably prime now */ 65 | *result = FP_YES; 66 | } 67 | -------------------------------------------------------------------------------- /src/numtheory/fp_prime_random_ex.c: -------------------------------------------------------------------------------- 1 | /* TomsFastMath, a fast ISO C bignum library. -- Tom St Denis */ 2 | /* SPDX-License-Identifier: Unlicense */ 3 | #include 4 | 5 | #define fp_on_bitnum(a, bitnum) \ 6 | a->dp[(bitnum) >> DIGIT_SHIFT] |= (fp_digit)1 << ((bitnum) & (DIGIT_BIT-1)) 7 | 8 | #define fp_off_bitnum(a, bitnum) \ 9 | a->dp[(bitnum) >> DIGIT_SHIFT] &= ~((fp_digit)1 << ((bitnum) & (DIGIT_BIT-1))) 10 | 11 | /* This is possibly the mother of all prime generation functions, muahahahahaha! */ 12 | int fp_prime_random_ex(fp_int *a, int t, int size, int flags, tfm_prime_callback cb, void *dat) 13 | { 14 | fp_digit maskAND_msb, maskOR_lsb; 15 | int res, bsize, dsize; 16 | unsigned char buf[FP_SIZE * sizeof(fp_digit)]; 17 | 18 | /* sanity check the input */ 19 | if (size <= 1 || cb == NULL || t <= 0 || t > FP_PRIME_SIZE) { 20 | return FP_VAL; 21 | } 22 | 23 | /* TFM_PRIME_SAFE implies TFM_PRIME_BBS */ 24 | if (flags & TFM_PRIME_SAFE) { 25 | flags |= TFM_PRIME_BBS; 26 | } 27 | 28 | /* calc the size in fp_digit */ 29 | dsize = (size + DIGIT_BIT - 1) >> DIGIT_SHIFT; 30 | /* calc the size in bytes */ 31 | bsize = (size + 7) >> 3; 32 | 33 | /* calc the maskAND value for the MSbyte */ 34 | maskAND_msb = FP_MASK >> ((DIGIT_BIT - size) & (DIGIT_BIT-1)); 35 | 36 | /* get the maskOR_lsb */ 37 | maskOR_lsb = 1; 38 | if (flags & TFM_PRIME_BBS) { 39 | maskOR_lsb |= 3; 40 | } 41 | 42 | do { 43 | /* read the bytes */ 44 | if (cb(buf, bsize, dat) != bsize) { 45 | return FP_VAL; 46 | } 47 | fp_read_unsigned_bin(a, buf, bsize); 48 | 49 | /* make sure the MSbyte has the required number of bits */ 50 | a->dp[dsize-1] &= maskAND_msb; 51 | 52 | /* Force a->used as well, it could be smaller if the highest bits were 53 | generated as 0 by the callback. */ 54 | a->used = dsize; 55 | 56 | /* modify the LSbyte as requested */ 57 | a->dp[0] |= maskOR_lsb; 58 | 59 | /* turn on the MSbit to force the requested magnitude */ 60 | fp_on_bitnum(a, size-1); 61 | 62 | /* modify the 2nd MSBit */ 63 | if (flags & TFM_PRIME_2MSB_ON) { 64 | fp_on_bitnum(a, size-2); 65 | } else if (flags & TFM_PRIME_2MSB_OFF) { 66 | fp_off_bitnum(a, size-2); 67 | } 68 | 69 | /* is it prime? */ 70 | res = fp_isprime_ex(a, t); 71 | if (res == FP_NO) continue; 72 | 73 | if (flags & TFM_PRIME_SAFE) { 74 | /* see if (a-1)/2 is prime */ 75 | fp_sub_d(a, 1, a); 76 | fp_div_2(a, a); 77 | 78 | /* is it prime? */ 79 | res = fp_isprime_ex(a, t); 80 | } 81 | } while (res == FP_NO); 82 | 83 | if (flags & TFM_PRIME_SAFE) { 84 | /* restore a to the original value */ 85 | fp_mul_2(a, a); 86 | fp_add_d(a, 1, a); 87 | } 88 | 89 | return FP_OKAY; 90 | } 91 | -------------------------------------------------------------------------------- /src/sqr/fp_sqr.c: -------------------------------------------------------------------------------- 1 | /* TomsFastMath, a fast ISO C bignum library. -- Tom St Denis */ 2 | /* SPDX-License-Identifier: Unlicense */ 3 | #include 4 | 5 | /* b = a*a */ 6 | void fp_sqr(const fp_int *A, fp_int *B) 7 | { 8 | int y, old_used; 9 | 10 | old_used = B->used; 11 | 12 | /* call generic if we're out of range */ 13 | if (A->used + A->used > FP_SIZE) { 14 | fp_sqr_comba(A, B); 15 | goto clean; 16 | } 17 | 18 | y = A->used; 19 | #if defined(TFM_SQR3) && FP_SIZE >= 6 20 | if (y <= 3) { 21 | fp_sqr_comba3(A,B); 22 | goto clean; 23 | } 24 | #endif 25 | #if defined(TFM_SQR4) && FP_SIZE >= 8 26 | if (y == 4) { 27 | fp_sqr_comba4(A,B); 28 | goto clean; 29 | } 30 | #endif 31 | #if defined(TFM_SQR6) && FP_SIZE >= 12 32 | if (y <= 6) { 33 | fp_sqr_comba6(A,B); 34 | goto clean; 35 | } 36 | #endif 37 | #if defined(TFM_SQR7) && FP_SIZE >= 14 38 | if (y == 7) { 39 | fp_sqr_comba7(A,B); 40 | goto clean; 41 | } 42 | #endif 43 | #if defined(TFM_SQR8) && FP_SIZE >= 16 44 | if (y == 8) { 45 | fp_sqr_comba8(A,B); 46 | goto clean; 47 | } 48 | #endif 49 | #if defined(TFM_SQR9) && FP_SIZE >= 18 50 | if (y == 9) { 51 | fp_sqr_comba9(A,B); 52 | goto clean; 53 | } 54 | #endif 55 | #if defined(TFM_SQR12) && FP_SIZE >= 24 56 | if (y <= 12) { 57 | fp_sqr_comba12(A,B); 58 | goto clean; 59 | } 60 | #endif 61 | #if defined(TFM_SQR17) && FP_SIZE >= 34 62 | if (y <= 17) { 63 | fp_sqr_comba17(A,B); 64 | goto clean; 65 | } 66 | #endif 67 | #if defined(TFM_SMALL_SET) 68 | if (y <= 16) { 69 | fp_sqr_comba_small(A,B); 70 | goto clean; 71 | } 72 | #endif 73 | #if defined(TFM_SQR20) && FP_SIZE >= 40 74 | if (y <= 20) { 75 | fp_sqr_comba20(A,B); 76 | goto clean; 77 | } 78 | #endif 79 | #if defined(TFM_SQR24) && FP_SIZE >= 48 80 | if (y <= 24) { 81 | fp_sqr_comba24(A,B); 82 | goto clean; 83 | } 84 | #endif 85 | #if defined(TFM_SQR28) && FP_SIZE >= 56 86 | if (y <= 28) { 87 | fp_sqr_comba28(A,B); 88 | goto clean; 89 | } 90 | #endif 91 | #if defined(TFM_SQR32) && FP_SIZE >= 64 92 | if (y <= 32) { 93 | fp_sqr_comba32(A,B); 94 | goto clean; 95 | } 96 | #endif 97 | #if defined(TFM_SQR48) && FP_SIZE >= 96 98 | if (y <= 48) { 99 | fp_sqr_comba48(A,B); 100 | goto clean; 101 | } 102 | #endif 103 | #if defined(TFM_SQR64) && FP_SIZE >= 128 104 | if (y <= 64) { 105 | fp_sqr_comba64(A,B); 106 | goto clean; 107 | } 108 | #endif 109 | fp_sqr_comba(A, B); 110 | clean: 111 | for (y = B->used; y < old_used; y++) { 112 | B->dp[y] = 0; 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /src/sqr/fp_sqr_comba_12.c: -------------------------------------------------------------------------------- 1 | /* TomsFastMath, a fast ISO C bignum library. -- Tom St Denis */ 2 | /* SPDX-License-Identifier: Unlicense */ 3 | #ifndef TFM_PRE_GEN_MPI_C 4 | #define TFM_DEFINES 5 | #include "fp_sqr_comba.c" 6 | #endif 7 | 8 | #if defined(TFM_SQR12) && FP_SIZE >= 24 9 | void fp_sqr_comba12(const fp_int *A, fp_int *B) 10 | { 11 | const fp_digit *a; 12 | fp_digit b[24], c0, c1, c2; 13 | fp_digit sc0, sc1, sc2; 14 | #ifdef TFM_ISO 15 | fp_word tt; 16 | #endif 17 | 18 | a = A->dp; 19 | COMBA_START; 20 | 21 | /* clear carries */ 22 | CLEAR_CARRY; 23 | 24 | /* output 0 */ 25 | SQRADD(a[0],a[0]); 26 | COMBA_STORE(b[0]); 27 | 28 | /* output 1 */ 29 | CARRY_FORWARD; 30 | SQRADD2(a[0], a[1]); 31 | COMBA_STORE(b[1]); 32 | 33 | /* output 2 */ 34 | CARRY_FORWARD; 35 | SQRADD2(a[0], a[2]); SQRADD(a[1], a[1]); 36 | COMBA_STORE(b[2]); 37 | 38 | /* output 3 */ 39 | CARRY_FORWARD; 40 | SQRADD2(a[0], a[3]); SQRADD2(a[1], a[2]); 41 | COMBA_STORE(b[3]); 42 | 43 | /* output 4 */ 44 | CARRY_FORWARD; 45 | SQRADD2(a[0], a[4]); SQRADD2(a[1], a[3]); SQRADD(a[2], a[2]); 46 | COMBA_STORE(b[4]); 47 | 48 | /* output 5 */ 49 | CARRY_FORWARD; 50 | SQRADDSC(a[0], a[5]); SQRADDAC(a[1], a[4]); SQRADDAC(a[2], a[3]); SQRADDDB; 51 | COMBA_STORE(b[5]); 52 | 53 | /* output 6 */ 54 | CARRY_FORWARD; 55 | SQRADDSC(a[0], a[6]); SQRADDAC(a[1], a[5]); SQRADDAC(a[2], a[4]); SQRADDDB; SQRADD(a[3], a[3]); 56 | COMBA_STORE(b[6]); 57 | 58 | /* output 7 */ 59 | CARRY_FORWARD; 60 | SQRADDSC(a[0], a[7]); SQRADDAC(a[1], a[6]); SQRADDAC(a[2], a[5]); SQRADDAC(a[3], a[4]); SQRADDDB; 61 | COMBA_STORE(b[7]); 62 | 63 | /* output 8 */ 64 | CARRY_FORWARD; 65 | SQRADDSC(a[0], a[8]); SQRADDAC(a[1], a[7]); SQRADDAC(a[2], a[6]); SQRADDAC(a[3], a[5]); SQRADDDB; SQRADD(a[4], a[4]); 66 | COMBA_STORE(b[8]); 67 | 68 | /* output 9 */ 69 | CARRY_FORWARD; 70 | SQRADDSC(a[0], a[9]); SQRADDAC(a[1], a[8]); SQRADDAC(a[2], a[7]); SQRADDAC(a[3], a[6]); SQRADDAC(a[4], a[5]); SQRADDDB; 71 | COMBA_STORE(b[9]); 72 | 73 | /* output 10 */ 74 | CARRY_FORWARD; 75 | SQRADDSC(a[0], a[10]); SQRADDAC(a[1], a[9]); SQRADDAC(a[2], a[8]); SQRADDAC(a[3], a[7]); SQRADDAC(a[4], a[6]); SQRADDDB; SQRADD(a[5], a[5]); 76 | COMBA_STORE(b[10]); 77 | 78 | /* output 11 */ 79 | CARRY_FORWARD; 80 | SQRADDSC(a[0], a[11]); SQRADDAC(a[1], a[10]); SQRADDAC(a[2], a[9]); SQRADDAC(a[3], a[8]); SQRADDAC(a[4], a[7]); SQRADDAC(a[5], a[6]); SQRADDDB; 81 | COMBA_STORE(b[11]); 82 | 83 | /* output 12 */ 84 | CARRY_FORWARD; 85 | SQRADDSC(a[1], a[11]); SQRADDAC(a[2], a[10]); SQRADDAC(a[3], a[9]); SQRADDAC(a[4], a[8]); SQRADDAC(a[5], a[7]); SQRADDDB; SQRADD(a[6], a[6]); 86 | COMBA_STORE(b[12]); 87 | 88 | /* output 13 */ 89 | CARRY_FORWARD; 90 | SQRADDSC(a[2], a[11]); SQRADDAC(a[3], a[10]); SQRADDAC(a[4], a[9]); SQRADDAC(a[5], a[8]); SQRADDAC(a[6], a[7]); SQRADDDB; 91 | COMBA_STORE(b[13]); 92 | 93 | /* output 14 */ 94 | CARRY_FORWARD; 95 | SQRADDSC(a[3], a[11]); SQRADDAC(a[4], a[10]); SQRADDAC(a[5], a[9]); SQRADDAC(a[6], a[8]); SQRADDDB; SQRADD(a[7], a[7]); 96 | COMBA_STORE(b[14]); 97 | 98 | /* output 15 */ 99 | CARRY_FORWARD; 100 | SQRADDSC(a[4], a[11]); SQRADDAC(a[5], a[10]); SQRADDAC(a[6], a[9]); SQRADDAC(a[7], a[8]); SQRADDDB; 101 | COMBA_STORE(b[15]); 102 | 103 | /* output 16 */ 104 | CARRY_FORWARD; 105 | SQRADDSC(a[5], a[11]); SQRADDAC(a[6], a[10]); SQRADDAC(a[7], a[9]); SQRADDDB; SQRADD(a[8], a[8]); 106 | COMBA_STORE(b[16]); 107 | 108 | /* output 17 */ 109 | CARRY_FORWARD; 110 | SQRADDSC(a[6], a[11]); SQRADDAC(a[7], a[10]); SQRADDAC(a[8], a[9]); SQRADDDB; 111 | COMBA_STORE(b[17]); 112 | 113 | /* output 18 */ 114 | CARRY_FORWARD; 115 | SQRADD2(a[7], a[11]); SQRADD2(a[8], a[10]); SQRADD(a[9], a[9]); 116 | COMBA_STORE(b[18]); 117 | 118 | /* output 19 */ 119 | CARRY_FORWARD; 120 | SQRADD2(a[8], a[11]); SQRADD2(a[9], a[10]); 121 | COMBA_STORE(b[19]); 122 | 123 | /* output 20 */ 124 | CARRY_FORWARD; 125 | SQRADD2(a[9], a[11]); SQRADD(a[10], a[10]); 126 | COMBA_STORE(b[20]); 127 | 128 | /* output 21 */ 129 | CARRY_FORWARD; 130 | SQRADD2(a[10], a[11]); 131 | COMBA_STORE(b[21]); 132 | 133 | /* output 22 */ 134 | CARRY_FORWARD; 135 | SQRADD(a[11], a[11]); 136 | COMBA_STORE(b[22]); 137 | COMBA_STORE2(b[23]); 138 | COMBA_FINI; 139 | 140 | B->used = 24; 141 | B->sign = FP_ZPOS; 142 | memcpy(B->dp, b, 24 * sizeof(fp_digit)); 143 | fp_clamp(B); 144 | } 145 | #endif 146 | -------------------------------------------------------------------------------- /src/sqr/fp_sqr_comba_17.c: -------------------------------------------------------------------------------- 1 | /* TomsFastMath, a fast ISO C bignum library. -- Tom St Denis */ 2 | /* SPDX-License-Identifier: Unlicense */ 3 | #ifndef TFM_PRE_GEN_MPI_C 4 | #define TFM_DEFINES 5 | #include "fp_sqr_comba.c" 6 | #endif 7 | 8 | #if defined(TFM_SQR17) && FP_SIZE >= 34 9 | void fp_sqr_comba17(const fp_int *A, fp_int *B) 10 | { 11 | const fp_digit *a; 12 | fp_digit b[34], c0, c1, c2; 13 | fp_digit sc0, sc1, sc2; 14 | #ifdef TFM_ISO 15 | fp_word tt; 16 | #endif 17 | 18 | a = A->dp; 19 | COMBA_START; 20 | 21 | /* clear carries */ 22 | CLEAR_CARRY; 23 | 24 | /* output 0 */ 25 | SQRADD(a[0],a[0]); 26 | COMBA_STORE(b[0]); 27 | 28 | /* output 1 */ 29 | CARRY_FORWARD; 30 | SQRADD2(a[0], a[1]); 31 | COMBA_STORE(b[1]); 32 | 33 | /* output 2 */ 34 | CARRY_FORWARD; 35 | SQRADD2(a[0], a[2]); SQRADD(a[1], a[1]); 36 | COMBA_STORE(b[2]); 37 | 38 | /* output 3 */ 39 | CARRY_FORWARD; 40 | SQRADD2(a[0], a[3]); SQRADD2(a[1], a[2]); 41 | COMBA_STORE(b[3]); 42 | 43 | /* output 4 */ 44 | CARRY_FORWARD; 45 | SQRADD2(a[0], a[4]); SQRADD2(a[1], a[3]); SQRADD(a[2], a[2]); 46 | COMBA_STORE(b[4]); 47 | 48 | /* output 5 */ 49 | CARRY_FORWARD; 50 | SQRADDSC(a[0], a[5]); SQRADDAC(a[1], a[4]); SQRADDAC(a[2], a[3]); SQRADDDB; 51 | COMBA_STORE(b[5]); 52 | 53 | /* output 6 */ 54 | CARRY_FORWARD; 55 | SQRADDSC(a[0], a[6]); SQRADDAC(a[1], a[5]); SQRADDAC(a[2], a[4]); SQRADDDB; SQRADD(a[3], a[3]); 56 | COMBA_STORE(b[6]); 57 | 58 | /* output 7 */ 59 | CARRY_FORWARD; 60 | SQRADDSC(a[0], a[7]); SQRADDAC(a[1], a[6]); SQRADDAC(a[2], a[5]); SQRADDAC(a[3], a[4]); SQRADDDB; 61 | COMBA_STORE(b[7]); 62 | 63 | /* output 8 */ 64 | CARRY_FORWARD; 65 | SQRADDSC(a[0], a[8]); SQRADDAC(a[1], a[7]); SQRADDAC(a[2], a[6]); SQRADDAC(a[3], a[5]); SQRADDDB; SQRADD(a[4], a[4]); 66 | COMBA_STORE(b[8]); 67 | 68 | /* output 9 */ 69 | CARRY_FORWARD; 70 | SQRADDSC(a[0], a[9]); SQRADDAC(a[1], a[8]); SQRADDAC(a[2], a[7]); SQRADDAC(a[3], a[6]); SQRADDAC(a[4], a[5]); SQRADDDB; 71 | COMBA_STORE(b[9]); 72 | 73 | /* output 10 */ 74 | CARRY_FORWARD; 75 | SQRADDSC(a[0], a[10]); SQRADDAC(a[1], a[9]); SQRADDAC(a[2], a[8]); SQRADDAC(a[3], a[7]); SQRADDAC(a[4], a[6]); SQRADDDB; SQRADD(a[5], a[5]); 76 | COMBA_STORE(b[10]); 77 | 78 | /* output 11 */ 79 | CARRY_FORWARD; 80 | SQRADDSC(a[0], a[11]); SQRADDAC(a[1], a[10]); SQRADDAC(a[2], a[9]); SQRADDAC(a[3], a[8]); SQRADDAC(a[4], a[7]); SQRADDAC(a[5], a[6]); SQRADDDB; 81 | COMBA_STORE(b[11]); 82 | 83 | /* output 12 */ 84 | CARRY_FORWARD; 85 | SQRADDSC(a[0], a[12]); SQRADDAC(a[1], a[11]); SQRADDAC(a[2], a[10]); SQRADDAC(a[3], a[9]); SQRADDAC(a[4], a[8]); SQRADDAC(a[5], a[7]); SQRADDDB; SQRADD(a[6], a[6]); 86 | COMBA_STORE(b[12]); 87 | 88 | /* output 13 */ 89 | CARRY_FORWARD; 90 | SQRADDSC(a[0], a[13]); SQRADDAC(a[1], a[12]); SQRADDAC(a[2], a[11]); SQRADDAC(a[3], a[10]); SQRADDAC(a[4], a[9]); SQRADDAC(a[5], a[8]); SQRADDAC(a[6], a[7]); SQRADDDB; 91 | COMBA_STORE(b[13]); 92 | 93 | /* output 14 */ 94 | CARRY_FORWARD; 95 | SQRADDSC(a[0], a[14]); SQRADDAC(a[1], a[13]); SQRADDAC(a[2], a[12]); SQRADDAC(a[3], a[11]); SQRADDAC(a[4], a[10]); SQRADDAC(a[5], a[9]); SQRADDAC(a[6], a[8]); SQRADDDB; SQRADD(a[7], a[7]); 96 | COMBA_STORE(b[14]); 97 | 98 | /* output 15 */ 99 | CARRY_FORWARD; 100 | SQRADDSC(a[0], a[15]); SQRADDAC(a[1], a[14]); SQRADDAC(a[2], a[13]); SQRADDAC(a[3], a[12]); SQRADDAC(a[4], a[11]); SQRADDAC(a[5], a[10]); SQRADDAC(a[6], a[9]); SQRADDAC(a[7], a[8]); SQRADDDB; 101 | COMBA_STORE(b[15]); 102 | 103 | /* output 16 */ 104 | CARRY_FORWARD; 105 | SQRADDSC(a[0], a[16]); SQRADDAC(a[1], a[15]); SQRADDAC(a[2], a[14]); SQRADDAC(a[3], a[13]); SQRADDAC(a[4], a[12]); SQRADDAC(a[5], a[11]); SQRADDAC(a[6], a[10]); SQRADDAC(a[7], a[9]); SQRADDDB; SQRADD(a[8], a[8]); 106 | COMBA_STORE(b[16]); 107 | 108 | /* output 17 */ 109 | CARRY_FORWARD; 110 | SQRADDSC(a[1], a[16]); SQRADDAC(a[2], a[15]); SQRADDAC(a[3], a[14]); SQRADDAC(a[4], a[13]); SQRADDAC(a[5], a[12]); SQRADDAC(a[6], a[11]); SQRADDAC(a[7], a[10]); SQRADDAC(a[8], a[9]); SQRADDDB; 111 | COMBA_STORE(b[17]); 112 | 113 | /* output 18 */ 114 | CARRY_FORWARD; 115 | SQRADDSC(a[2], a[16]); SQRADDAC(a[3], a[15]); SQRADDAC(a[4], a[14]); SQRADDAC(a[5], a[13]); SQRADDAC(a[6], a[12]); SQRADDAC(a[7], a[11]); SQRADDAC(a[8], a[10]); SQRADDDB; SQRADD(a[9], a[9]); 116 | COMBA_STORE(b[18]); 117 | 118 | /* output 19 */ 119 | CARRY_FORWARD; 120 | SQRADDSC(a[3], a[16]); SQRADDAC(a[4], a[15]); SQRADDAC(a[5], a[14]); SQRADDAC(a[6], a[13]); SQRADDAC(a[7], a[12]); SQRADDAC(a[8], a[11]); SQRADDAC(a[9], a[10]); SQRADDDB; 121 | COMBA_STORE(b[19]); 122 | 123 | /* output 20 */ 124 | CARRY_FORWARD; 125 | SQRADDSC(a[4], a[16]); SQRADDAC(a[5], a[15]); SQRADDAC(a[6], a[14]); SQRADDAC(a[7], a[13]); SQRADDAC(a[8], a[12]); SQRADDAC(a[9], a[11]); SQRADDDB; SQRADD(a[10], a[10]); 126 | COMBA_STORE(b[20]); 127 | 128 | /* output 21 */ 129 | CARRY_FORWARD; 130 | SQRADDSC(a[5], a[16]); SQRADDAC(a[6], a[15]); SQRADDAC(a[7], a[14]); SQRADDAC(a[8], a[13]); SQRADDAC(a[9], a[12]); SQRADDAC(a[10], a[11]); SQRADDDB; 131 | COMBA_STORE(b[21]); 132 | 133 | /* output 22 */ 134 | CARRY_FORWARD; 135 | SQRADDSC(a[6], a[16]); SQRADDAC(a[7], a[15]); SQRADDAC(a[8], a[14]); SQRADDAC(a[9], a[13]); SQRADDAC(a[10], a[12]); SQRADDDB; SQRADD(a[11], a[11]); 136 | COMBA_STORE(b[22]); 137 | 138 | /* output 23 */ 139 | CARRY_FORWARD; 140 | SQRADDSC(a[7], a[16]); SQRADDAC(a[8], a[15]); SQRADDAC(a[9], a[14]); SQRADDAC(a[10], a[13]); SQRADDAC(a[11], a[12]); SQRADDDB; 141 | COMBA_STORE(b[23]); 142 | 143 | /* output 24 */ 144 | CARRY_FORWARD; 145 | SQRADDSC(a[8], a[16]); SQRADDAC(a[9], a[15]); SQRADDAC(a[10], a[14]); SQRADDAC(a[11], a[13]); SQRADDDB; SQRADD(a[12], a[12]); 146 | COMBA_STORE(b[24]); 147 | 148 | /* output 25 */ 149 | CARRY_FORWARD; 150 | SQRADDSC(a[9], a[16]); SQRADDAC(a[10], a[15]); SQRADDAC(a[11], a[14]); SQRADDAC(a[12], a[13]); SQRADDDB; 151 | COMBA_STORE(b[25]); 152 | 153 | /* output 26 */ 154 | CARRY_FORWARD; 155 | SQRADDSC(a[10], a[16]); SQRADDAC(a[11], a[15]); SQRADDAC(a[12], a[14]); SQRADDDB; SQRADD(a[13], a[13]); 156 | COMBA_STORE(b[26]); 157 | 158 | /* output 27 */ 159 | CARRY_FORWARD; 160 | SQRADDSC(a[11], a[16]); SQRADDAC(a[12], a[15]); SQRADDAC(a[13], a[14]); SQRADDDB; 161 | COMBA_STORE(b[27]); 162 | 163 | /* output 28 */ 164 | CARRY_FORWARD; 165 | SQRADD2(a[12], a[16]); SQRADD2(a[13], a[15]); SQRADD(a[14], a[14]); 166 | COMBA_STORE(b[28]); 167 | 168 | /* output 29 */ 169 | CARRY_FORWARD; 170 | SQRADD2(a[13], a[16]); SQRADD2(a[14], a[15]); 171 | COMBA_STORE(b[29]); 172 | 173 | /* output 30 */ 174 | CARRY_FORWARD; 175 | SQRADD2(a[14], a[16]); SQRADD(a[15], a[15]); 176 | COMBA_STORE(b[30]); 177 | 178 | /* output 31 */ 179 | CARRY_FORWARD; 180 | SQRADD2(a[15], a[16]); 181 | COMBA_STORE(b[31]); 182 | 183 | /* output 32 */ 184 | CARRY_FORWARD; 185 | SQRADD(a[16], a[16]); 186 | COMBA_STORE(b[32]); 187 | COMBA_STORE2(b[33]); 188 | COMBA_FINI; 189 | 190 | B->used = 34; 191 | B->sign = FP_ZPOS; 192 | memcpy(B->dp, b, 34 * sizeof(fp_digit)); 193 | fp_clamp(B); 194 | } 195 | #endif 196 | -------------------------------------------------------------------------------- /src/sqr/fp_sqr_comba_20.c: -------------------------------------------------------------------------------- 1 | /* TomsFastMath, a fast ISO C bignum library. -- Tom St Denis */ 2 | /* SPDX-License-Identifier: Unlicense */ 3 | #ifndef TFM_PRE_GEN_MPI_C 4 | #define TFM_DEFINES 5 | #include "fp_sqr_comba.c" 6 | #endif 7 | 8 | #if defined(TFM_SQR20) && FP_SIZE >= 40 9 | void fp_sqr_comba20(const fp_int *A, fp_int *B) 10 | { 11 | const fp_digit *a; 12 | fp_digit b[40], c0, c1, c2; 13 | fp_digit sc0, sc1, sc2; 14 | #ifdef TFM_ISO 15 | fp_word tt; 16 | #endif 17 | 18 | a = A->dp; 19 | COMBA_START; 20 | 21 | /* clear carries */ 22 | CLEAR_CARRY; 23 | 24 | /* output 0 */ 25 | SQRADD(a[0],a[0]); 26 | COMBA_STORE(b[0]); 27 | 28 | /* output 1 */ 29 | CARRY_FORWARD; 30 | SQRADD2(a[0], a[1]); 31 | COMBA_STORE(b[1]); 32 | 33 | /* output 2 */ 34 | CARRY_FORWARD; 35 | SQRADD2(a[0], a[2]); SQRADD(a[1], a[1]); 36 | COMBA_STORE(b[2]); 37 | 38 | /* output 3 */ 39 | CARRY_FORWARD; 40 | SQRADD2(a[0], a[3]); SQRADD2(a[1], a[2]); 41 | COMBA_STORE(b[3]); 42 | 43 | /* output 4 */ 44 | CARRY_FORWARD; 45 | SQRADD2(a[0], a[4]); SQRADD2(a[1], a[3]); SQRADD(a[2], a[2]); 46 | COMBA_STORE(b[4]); 47 | 48 | /* output 5 */ 49 | CARRY_FORWARD; 50 | SQRADDSC(a[0], a[5]); SQRADDAC(a[1], a[4]); SQRADDAC(a[2], a[3]); SQRADDDB; 51 | COMBA_STORE(b[5]); 52 | 53 | /* output 6 */ 54 | CARRY_FORWARD; 55 | SQRADDSC(a[0], a[6]); SQRADDAC(a[1], a[5]); SQRADDAC(a[2], a[4]); SQRADDDB; SQRADD(a[3], a[3]); 56 | COMBA_STORE(b[6]); 57 | 58 | /* output 7 */ 59 | CARRY_FORWARD; 60 | SQRADDSC(a[0], a[7]); SQRADDAC(a[1], a[6]); SQRADDAC(a[2], a[5]); SQRADDAC(a[3], a[4]); SQRADDDB; 61 | COMBA_STORE(b[7]); 62 | 63 | /* output 8 */ 64 | CARRY_FORWARD; 65 | SQRADDSC(a[0], a[8]); SQRADDAC(a[1], a[7]); SQRADDAC(a[2], a[6]); SQRADDAC(a[3], a[5]); SQRADDDB; SQRADD(a[4], a[4]); 66 | COMBA_STORE(b[8]); 67 | 68 | /* output 9 */ 69 | CARRY_FORWARD; 70 | SQRADDSC(a[0], a[9]); SQRADDAC(a[1], a[8]); SQRADDAC(a[2], a[7]); SQRADDAC(a[3], a[6]); SQRADDAC(a[4], a[5]); SQRADDDB; 71 | COMBA_STORE(b[9]); 72 | 73 | /* output 10 */ 74 | CARRY_FORWARD; 75 | SQRADDSC(a[0], a[10]); SQRADDAC(a[1], a[9]); SQRADDAC(a[2], a[8]); SQRADDAC(a[3], a[7]); SQRADDAC(a[4], a[6]); SQRADDDB; SQRADD(a[5], a[5]); 76 | COMBA_STORE(b[10]); 77 | 78 | /* output 11 */ 79 | CARRY_FORWARD; 80 | SQRADDSC(a[0], a[11]); SQRADDAC(a[1], a[10]); SQRADDAC(a[2], a[9]); SQRADDAC(a[3], a[8]); SQRADDAC(a[4], a[7]); SQRADDAC(a[5], a[6]); SQRADDDB; 81 | COMBA_STORE(b[11]); 82 | 83 | /* output 12 */ 84 | CARRY_FORWARD; 85 | SQRADDSC(a[0], a[12]); SQRADDAC(a[1], a[11]); SQRADDAC(a[2], a[10]); SQRADDAC(a[3], a[9]); SQRADDAC(a[4], a[8]); SQRADDAC(a[5], a[7]); SQRADDDB; SQRADD(a[6], a[6]); 86 | COMBA_STORE(b[12]); 87 | 88 | /* output 13 */ 89 | CARRY_FORWARD; 90 | SQRADDSC(a[0], a[13]); SQRADDAC(a[1], a[12]); SQRADDAC(a[2], a[11]); SQRADDAC(a[3], a[10]); SQRADDAC(a[4], a[9]); SQRADDAC(a[5], a[8]); SQRADDAC(a[6], a[7]); SQRADDDB; 91 | COMBA_STORE(b[13]); 92 | 93 | /* output 14 */ 94 | CARRY_FORWARD; 95 | SQRADDSC(a[0], a[14]); SQRADDAC(a[1], a[13]); SQRADDAC(a[2], a[12]); SQRADDAC(a[3], a[11]); SQRADDAC(a[4], a[10]); SQRADDAC(a[5], a[9]); SQRADDAC(a[6], a[8]); SQRADDDB; SQRADD(a[7], a[7]); 96 | COMBA_STORE(b[14]); 97 | 98 | /* output 15 */ 99 | CARRY_FORWARD; 100 | SQRADDSC(a[0], a[15]); SQRADDAC(a[1], a[14]); SQRADDAC(a[2], a[13]); SQRADDAC(a[3], a[12]); SQRADDAC(a[4], a[11]); SQRADDAC(a[5], a[10]); SQRADDAC(a[6], a[9]); SQRADDAC(a[7], a[8]); SQRADDDB; 101 | COMBA_STORE(b[15]); 102 | 103 | /* output 16 */ 104 | CARRY_FORWARD; 105 | SQRADDSC(a[0], a[16]); SQRADDAC(a[1], a[15]); SQRADDAC(a[2], a[14]); SQRADDAC(a[3], a[13]); SQRADDAC(a[4], a[12]); SQRADDAC(a[5], a[11]); SQRADDAC(a[6], a[10]); SQRADDAC(a[7], a[9]); SQRADDDB; SQRADD(a[8], a[8]); 106 | COMBA_STORE(b[16]); 107 | 108 | /* output 17 */ 109 | CARRY_FORWARD; 110 | SQRADDSC(a[0], a[17]); SQRADDAC(a[1], a[16]); SQRADDAC(a[2], a[15]); SQRADDAC(a[3], a[14]); SQRADDAC(a[4], a[13]); SQRADDAC(a[5], a[12]); SQRADDAC(a[6], a[11]); SQRADDAC(a[7], a[10]); SQRADDAC(a[8], a[9]); SQRADDDB; 111 | COMBA_STORE(b[17]); 112 | 113 | /* output 18 */ 114 | CARRY_FORWARD; 115 | SQRADDSC(a[0], a[18]); SQRADDAC(a[1], a[17]); SQRADDAC(a[2], a[16]); SQRADDAC(a[3], a[15]); SQRADDAC(a[4], a[14]); SQRADDAC(a[5], a[13]); SQRADDAC(a[6], a[12]); SQRADDAC(a[7], a[11]); SQRADDAC(a[8], a[10]); SQRADDDB; SQRADD(a[9], a[9]); 116 | COMBA_STORE(b[18]); 117 | 118 | /* output 19 */ 119 | CARRY_FORWARD; 120 | SQRADDSC(a[0], a[19]); SQRADDAC(a[1], a[18]); SQRADDAC(a[2], a[17]); SQRADDAC(a[3], a[16]); SQRADDAC(a[4], a[15]); SQRADDAC(a[5], a[14]); SQRADDAC(a[6], a[13]); SQRADDAC(a[7], a[12]); SQRADDAC(a[8], a[11]); SQRADDAC(a[9], a[10]); SQRADDDB; 121 | COMBA_STORE(b[19]); 122 | 123 | /* output 20 */ 124 | CARRY_FORWARD; 125 | SQRADDSC(a[1], a[19]); SQRADDAC(a[2], a[18]); SQRADDAC(a[3], a[17]); SQRADDAC(a[4], a[16]); SQRADDAC(a[5], a[15]); SQRADDAC(a[6], a[14]); SQRADDAC(a[7], a[13]); SQRADDAC(a[8], a[12]); SQRADDAC(a[9], a[11]); SQRADDDB; SQRADD(a[10], a[10]); 126 | COMBA_STORE(b[20]); 127 | 128 | /* output 21 */ 129 | CARRY_FORWARD; 130 | SQRADDSC(a[2], a[19]); SQRADDAC(a[3], a[18]); SQRADDAC(a[4], a[17]); SQRADDAC(a[5], a[16]); SQRADDAC(a[6], a[15]); SQRADDAC(a[7], a[14]); SQRADDAC(a[8], a[13]); SQRADDAC(a[9], a[12]); SQRADDAC(a[10], a[11]); SQRADDDB; 131 | COMBA_STORE(b[21]); 132 | 133 | /* output 22 */ 134 | CARRY_FORWARD; 135 | SQRADDSC(a[3], a[19]); SQRADDAC(a[4], a[18]); SQRADDAC(a[5], a[17]); SQRADDAC(a[6], a[16]); SQRADDAC(a[7], a[15]); SQRADDAC(a[8], a[14]); SQRADDAC(a[9], a[13]); SQRADDAC(a[10], a[12]); SQRADDDB; SQRADD(a[11], a[11]); 136 | COMBA_STORE(b[22]); 137 | 138 | /* output 23 */ 139 | CARRY_FORWARD; 140 | SQRADDSC(a[4], a[19]); SQRADDAC(a[5], a[18]); SQRADDAC(a[6], a[17]); SQRADDAC(a[7], a[16]); SQRADDAC(a[8], a[15]); SQRADDAC(a[9], a[14]); SQRADDAC(a[10], a[13]); SQRADDAC(a[11], a[12]); SQRADDDB; 141 | COMBA_STORE(b[23]); 142 | 143 | /* output 24 */ 144 | CARRY_FORWARD; 145 | SQRADDSC(a[5], a[19]); SQRADDAC(a[6], a[18]); SQRADDAC(a[7], a[17]); SQRADDAC(a[8], a[16]); SQRADDAC(a[9], a[15]); SQRADDAC(a[10], a[14]); SQRADDAC(a[11], a[13]); SQRADDDB; SQRADD(a[12], a[12]); 146 | COMBA_STORE(b[24]); 147 | 148 | /* output 25 */ 149 | CARRY_FORWARD; 150 | SQRADDSC(a[6], a[19]); SQRADDAC(a[7], a[18]); SQRADDAC(a[8], a[17]); SQRADDAC(a[9], a[16]); SQRADDAC(a[10], a[15]); SQRADDAC(a[11], a[14]); SQRADDAC(a[12], a[13]); SQRADDDB; 151 | COMBA_STORE(b[25]); 152 | 153 | /* output 26 */ 154 | CARRY_FORWARD; 155 | SQRADDSC(a[7], a[19]); SQRADDAC(a[8], a[18]); SQRADDAC(a[9], a[17]); SQRADDAC(a[10], a[16]); SQRADDAC(a[11], a[15]); SQRADDAC(a[12], a[14]); SQRADDDB; SQRADD(a[13], a[13]); 156 | COMBA_STORE(b[26]); 157 | 158 | /* output 27 */ 159 | CARRY_FORWARD; 160 | SQRADDSC(a[8], a[19]); SQRADDAC(a[9], a[18]); SQRADDAC(a[10], a[17]); SQRADDAC(a[11], a[16]); SQRADDAC(a[12], a[15]); SQRADDAC(a[13], a[14]); SQRADDDB; 161 | COMBA_STORE(b[27]); 162 | 163 | /* output 28 */ 164 | CARRY_FORWARD; 165 | SQRADDSC(a[9], a[19]); SQRADDAC(a[10], a[18]); SQRADDAC(a[11], a[17]); SQRADDAC(a[12], a[16]); SQRADDAC(a[13], a[15]); SQRADDDB; SQRADD(a[14], a[14]); 166 | COMBA_STORE(b[28]); 167 | 168 | /* output 29 */ 169 | CARRY_FORWARD; 170 | SQRADDSC(a[10], a[19]); SQRADDAC(a[11], a[18]); SQRADDAC(a[12], a[17]); SQRADDAC(a[13], a[16]); SQRADDAC(a[14], a[15]); SQRADDDB; 171 | COMBA_STORE(b[29]); 172 | 173 | /* output 30 */ 174 | CARRY_FORWARD; 175 | SQRADDSC(a[11], a[19]); SQRADDAC(a[12], a[18]); SQRADDAC(a[13], a[17]); SQRADDAC(a[14], a[16]); SQRADDDB; SQRADD(a[15], a[15]); 176 | COMBA_STORE(b[30]); 177 | 178 | /* output 31 */ 179 | CARRY_FORWARD; 180 | SQRADDSC(a[12], a[19]); SQRADDAC(a[13], a[18]); SQRADDAC(a[14], a[17]); SQRADDAC(a[15], a[16]); SQRADDDB; 181 | COMBA_STORE(b[31]); 182 | 183 | /* output 32 */ 184 | CARRY_FORWARD; 185 | SQRADDSC(a[13], a[19]); SQRADDAC(a[14], a[18]); SQRADDAC(a[15], a[17]); SQRADDDB; SQRADD(a[16], a[16]); 186 | COMBA_STORE(b[32]); 187 | 188 | /* output 33 */ 189 | CARRY_FORWARD; 190 | SQRADDSC(a[14], a[19]); SQRADDAC(a[15], a[18]); SQRADDAC(a[16], a[17]); SQRADDDB; 191 | COMBA_STORE(b[33]); 192 | 193 | /* output 34 */ 194 | CARRY_FORWARD; 195 | SQRADD2(a[15], a[19]); SQRADD2(a[16], a[18]); SQRADD(a[17], a[17]); 196 | COMBA_STORE(b[34]); 197 | 198 | /* output 35 */ 199 | CARRY_FORWARD; 200 | SQRADD2(a[16], a[19]); SQRADD2(a[17], a[18]); 201 | COMBA_STORE(b[35]); 202 | 203 | /* output 36 */ 204 | CARRY_FORWARD; 205 | SQRADD2(a[17], a[19]); SQRADD(a[18], a[18]); 206 | COMBA_STORE(b[36]); 207 | 208 | /* output 37 */ 209 | CARRY_FORWARD; 210 | SQRADD2(a[18], a[19]); 211 | COMBA_STORE(b[37]); 212 | 213 | /* output 38 */ 214 | CARRY_FORWARD; 215 | SQRADD(a[19], a[19]); 216 | COMBA_STORE(b[38]); 217 | COMBA_STORE2(b[39]); 218 | COMBA_FINI; 219 | 220 | B->used = 40; 221 | B->sign = FP_ZPOS; 222 | memcpy(B->dp, b, 40 * sizeof(fp_digit)); 223 | fp_clamp(B); 224 | } 225 | #endif 226 | -------------------------------------------------------------------------------- /src/sqr/fp_sqr_comba_3.c: -------------------------------------------------------------------------------- 1 | /* TomsFastMath, a fast ISO C bignum library. -- Tom St Denis */ 2 | /* SPDX-License-Identifier: Unlicense */ 3 | #ifndef TFM_PRE_GEN_MPI_C 4 | #define TFM_DEFINES 5 | #include "fp_sqr_comba.c" 6 | #endif 7 | 8 | #if defined(TFM_SQR3) && FP_SIZE >= 6 9 | void fp_sqr_comba3(const fp_int *A, fp_int *B) 10 | { 11 | const fp_digit *a; 12 | fp_digit b[6], c0, c1, c2; 13 | #ifdef TFM_ISO 14 | fp_word tt; 15 | #endif 16 | 17 | a = A->dp; 18 | COMBA_START; 19 | 20 | /* clear carries */ 21 | CLEAR_CARRY; 22 | 23 | /* output 0 */ 24 | SQRADD(a[0],a[0]); 25 | COMBA_STORE(b[0]); 26 | 27 | /* output 1 */ 28 | CARRY_FORWARD; 29 | SQRADD2(a[0], a[1]); 30 | COMBA_STORE(b[1]); 31 | 32 | /* output 2 */ 33 | CARRY_FORWARD; 34 | SQRADD2(a[0], a[2]); SQRADD(a[1], a[1]); 35 | COMBA_STORE(b[2]); 36 | 37 | /* output 3 */ 38 | CARRY_FORWARD; 39 | SQRADD2(a[1], a[2]); 40 | COMBA_STORE(b[3]); 41 | 42 | /* output 4 */ 43 | CARRY_FORWARD; 44 | SQRADD(a[2], a[2]); 45 | COMBA_STORE(b[4]); 46 | COMBA_STORE2(b[5]); 47 | COMBA_FINI; 48 | 49 | B->used = 6; 50 | B->sign = FP_ZPOS; 51 | memcpy(B->dp, b, 6 * sizeof(fp_digit)); 52 | fp_clamp(B); 53 | } 54 | #endif 55 | -------------------------------------------------------------------------------- /src/sqr/fp_sqr_comba_4.c: -------------------------------------------------------------------------------- 1 | /* TomsFastMath, a fast ISO C bignum library. -- Tom St Denis */ 2 | /* SPDX-License-Identifier: Unlicense */ 3 | #ifndef TFM_PRE_GEN_MPI_C 4 | #define TFM_DEFINES 5 | #include "fp_sqr_comba.c" 6 | #endif 7 | 8 | #if defined(TFM_SQR4) && FP_SIZE >= 8 9 | void fp_sqr_comba4(const fp_int *A, fp_int *B) 10 | { 11 | const fp_digit *a; 12 | fp_digit b[8], c0, c1, c2; 13 | #ifdef TFM_ISO 14 | fp_word tt; 15 | #endif 16 | 17 | a = A->dp; 18 | COMBA_START; 19 | 20 | /* clear carries */ 21 | CLEAR_CARRY; 22 | 23 | /* output 0 */ 24 | SQRADD(a[0],a[0]); 25 | COMBA_STORE(b[0]); 26 | 27 | /* output 1 */ 28 | CARRY_FORWARD; 29 | SQRADD2(a[0], a[1]); 30 | COMBA_STORE(b[1]); 31 | 32 | /* output 2 */ 33 | CARRY_FORWARD; 34 | SQRADD2(a[0], a[2]); SQRADD(a[1], a[1]); 35 | COMBA_STORE(b[2]); 36 | 37 | /* output 3 */ 38 | CARRY_FORWARD; 39 | SQRADD2(a[0], a[3]); SQRADD2(a[1], a[2]); 40 | COMBA_STORE(b[3]); 41 | 42 | /* output 4 */ 43 | CARRY_FORWARD; 44 | SQRADD2(a[1], a[3]); SQRADD(a[2], a[2]); 45 | COMBA_STORE(b[4]); 46 | 47 | /* output 5 */ 48 | CARRY_FORWARD; 49 | SQRADD2(a[2], a[3]); 50 | COMBA_STORE(b[5]); 51 | 52 | /* output 6 */ 53 | CARRY_FORWARD; 54 | SQRADD(a[3], a[3]); 55 | COMBA_STORE(b[6]); 56 | COMBA_STORE2(b[7]); 57 | COMBA_FINI; 58 | 59 | B->used = 8; 60 | B->sign = FP_ZPOS; 61 | memcpy(B->dp, b, 8 * sizeof(fp_digit)); 62 | fp_clamp(B); 63 | } 64 | #endif 65 | -------------------------------------------------------------------------------- /src/sqr/fp_sqr_comba_6.c: -------------------------------------------------------------------------------- 1 | /* TomsFastMath, a fast ISO C bignum library. -- Tom St Denis */ 2 | /* SPDX-License-Identifier: Unlicense */ 3 | #ifndef TFM_PRE_GEN_MPI_C 4 | #define TFM_DEFINES 5 | #include "fp_sqr_comba.c" 6 | #endif 7 | 8 | #if defined(TFM_SQR6) && FP_SIZE >= 12 9 | void fp_sqr_comba6(const fp_int *A, fp_int *B) 10 | { 11 | const fp_digit *a; 12 | fp_digit b[12], c0, c1, c2; 13 | fp_digit sc0, sc1, sc2; 14 | #ifdef TFM_ISO 15 | fp_word tt; 16 | #endif 17 | 18 | a = A->dp; 19 | COMBA_START; 20 | 21 | /* clear carries */ 22 | CLEAR_CARRY; 23 | 24 | /* output 0 */ 25 | SQRADD(a[0],a[0]); 26 | COMBA_STORE(b[0]); 27 | 28 | /* output 1 */ 29 | CARRY_FORWARD; 30 | SQRADD2(a[0], a[1]); 31 | COMBA_STORE(b[1]); 32 | 33 | /* output 2 */ 34 | CARRY_FORWARD; 35 | SQRADD2(a[0], a[2]); SQRADD(a[1], a[1]); 36 | COMBA_STORE(b[2]); 37 | 38 | /* output 3 */ 39 | CARRY_FORWARD; 40 | SQRADD2(a[0], a[3]); SQRADD2(a[1], a[2]); 41 | COMBA_STORE(b[3]); 42 | 43 | /* output 4 */ 44 | CARRY_FORWARD; 45 | SQRADD2(a[0], a[4]); SQRADD2(a[1], a[3]); SQRADD(a[2], a[2]); 46 | COMBA_STORE(b[4]); 47 | 48 | /* output 5 */ 49 | CARRY_FORWARD; 50 | SQRADDSC(a[0], a[5]); SQRADDAC(a[1], a[4]); SQRADDAC(a[2], a[3]); SQRADDDB; 51 | COMBA_STORE(b[5]); 52 | 53 | /* output 6 */ 54 | CARRY_FORWARD; 55 | SQRADD2(a[1], a[5]); SQRADD2(a[2], a[4]); SQRADD(a[3], a[3]); 56 | COMBA_STORE(b[6]); 57 | 58 | /* output 7 */ 59 | CARRY_FORWARD; 60 | SQRADD2(a[2], a[5]); SQRADD2(a[3], a[4]); 61 | COMBA_STORE(b[7]); 62 | 63 | /* output 8 */ 64 | CARRY_FORWARD; 65 | SQRADD2(a[3], a[5]); SQRADD(a[4], a[4]); 66 | COMBA_STORE(b[8]); 67 | 68 | /* output 9 */ 69 | CARRY_FORWARD; 70 | SQRADD2(a[4], a[5]); 71 | COMBA_STORE(b[9]); 72 | 73 | /* output 10 */ 74 | CARRY_FORWARD; 75 | SQRADD(a[5], a[5]); 76 | COMBA_STORE(b[10]); 77 | COMBA_STORE2(b[11]); 78 | COMBA_FINI; 79 | 80 | B->used = 12; 81 | B->sign = FP_ZPOS; 82 | memcpy(B->dp, b, 12 * sizeof(fp_digit)); 83 | fp_clamp(B); 84 | } 85 | #endif 86 | -------------------------------------------------------------------------------- /src/sqr/fp_sqr_comba_7.c: -------------------------------------------------------------------------------- 1 | /* TomsFastMath, a fast ISO C bignum library. -- Tom St Denis */ 2 | /* SPDX-License-Identifier: Unlicense */ 3 | #ifndef TFM_PRE_GEN_MPI_C 4 | #define TFM_DEFINES 5 | #include "fp_sqr_comba.c" 6 | #endif 7 | 8 | #if defined(TFM_SQR7) && FP_SIZE >= 14 9 | void fp_sqr_comba7(const fp_int *A, fp_int *B) 10 | { 11 | const fp_digit *a; 12 | fp_digit b[14], c0, c1, c2; 13 | fp_digit sc0, sc1, sc2; 14 | #ifdef TFM_ISO 15 | fp_word tt; 16 | #endif 17 | 18 | a = A->dp; 19 | COMBA_START; 20 | 21 | /* clear carries */ 22 | CLEAR_CARRY; 23 | 24 | /* output 0 */ 25 | SQRADD(a[0],a[0]); 26 | COMBA_STORE(b[0]); 27 | 28 | /* output 1 */ 29 | CARRY_FORWARD; 30 | SQRADD2(a[0], a[1]); 31 | COMBA_STORE(b[1]); 32 | 33 | /* output 2 */ 34 | CARRY_FORWARD; 35 | SQRADD2(a[0], a[2]); SQRADD(a[1], a[1]); 36 | COMBA_STORE(b[2]); 37 | 38 | /* output 3 */ 39 | CARRY_FORWARD; 40 | SQRADD2(a[0], a[3]); SQRADD2(a[1], a[2]); 41 | COMBA_STORE(b[3]); 42 | 43 | /* output 4 */ 44 | CARRY_FORWARD; 45 | SQRADD2(a[0], a[4]); SQRADD2(a[1], a[3]); SQRADD(a[2], a[2]); 46 | COMBA_STORE(b[4]); 47 | 48 | /* output 5 */ 49 | CARRY_FORWARD; 50 | SQRADDSC(a[0], a[5]); SQRADDAC(a[1], a[4]); SQRADDAC(a[2], a[3]); SQRADDDB; 51 | COMBA_STORE(b[5]); 52 | 53 | /* output 6 */ 54 | CARRY_FORWARD; 55 | SQRADDSC(a[0], a[6]); SQRADDAC(a[1], a[5]); SQRADDAC(a[2], a[4]); SQRADDDB; SQRADD(a[3], a[3]); 56 | COMBA_STORE(b[6]); 57 | 58 | /* output 7 */ 59 | CARRY_FORWARD; 60 | SQRADDSC(a[1], a[6]); SQRADDAC(a[2], a[5]); SQRADDAC(a[3], a[4]); SQRADDDB; 61 | COMBA_STORE(b[7]); 62 | 63 | /* output 8 */ 64 | CARRY_FORWARD; 65 | SQRADD2(a[2], a[6]); SQRADD2(a[3], a[5]); SQRADD(a[4], a[4]); 66 | COMBA_STORE(b[8]); 67 | 68 | /* output 9 */ 69 | CARRY_FORWARD; 70 | SQRADD2(a[3], a[6]); SQRADD2(a[4], a[5]); 71 | COMBA_STORE(b[9]); 72 | 73 | /* output 10 */ 74 | CARRY_FORWARD; 75 | SQRADD2(a[4], a[6]); SQRADD(a[5], a[5]); 76 | COMBA_STORE(b[10]); 77 | 78 | /* output 11 */ 79 | CARRY_FORWARD; 80 | SQRADD2(a[5], a[6]); 81 | COMBA_STORE(b[11]); 82 | 83 | /* output 12 */ 84 | CARRY_FORWARD; 85 | SQRADD(a[6], a[6]); 86 | COMBA_STORE(b[12]); 87 | COMBA_STORE2(b[13]); 88 | COMBA_FINI; 89 | 90 | B->used = 14; 91 | B->sign = FP_ZPOS; 92 | memcpy(B->dp, b, 14 * sizeof(fp_digit)); 93 | fp_clamp(B); 94 | } 95 | #endif 96 | -------------------------------------------------------------------------------- /src/sqr/fp_sqr_comba_8.c: -------------------------------------------------------------------------------- 1 | /* TomsFastMath, a fast ISO C bignum library. -- Tom St Denis */ 2 | /* SPDX-License-Identifier: Unlicense */ 3 | #ifndef TFM_PRE_GEN_MPI_C 4 | #define TFM_DEFINES 5 | #include "fp_sqr_comba.c" 6 | #endif 7 | 8 | #if defined(TFM_SQR8) && FP_SIZE >= 16 9 | void fp_sqr_comba8(const fp_int *A, fp_int *B) 10 | { 11 | const fp_digit *a; 12 | fp_digit b[16], c0, c1, c2; 13 | fp_digit sc0, sc1, sc2; 14 | #ifdef TFM_ISO 15 | fp_word tt; 16 | #endif 17 | 18 | a = A->dp; 19 | COMBA_START; 20 | 21 | /* clear carries */ 22 | CLEAR_CARRY; 23 | 24 | /* output 0 */ 25 | SQRADD(a[0],a[0]); 26 | COMBA_STORE(b[0]); 27 | 28 | /* output 1 */ 29 | CARRY_FORWARD; 30 | SQRADD2(a[0], a[1]); 31 | COMBA_STORE(b[1]); 32 | 33 | /* output 2 */ 34 | CARRY_FORWARD; 35 | SQRADD2(a[0], a[2]); SQRADD(a[1], a[1]); 36 | COMBA_STORE(b[2]); 37 | 38 | /* output 3 */ 39 | CARRY_FORWARD; 40 | SQRADD2(a[0], a[3]); SQRADD2(a[1], a[2]); 41 | COMBA_STORE(b[3]); 42 | 43 | /* output 4 */ 44 | CARRY_FORWARD; 45 | SQRADD2(a[0], a[4]); SQRADD2(a[1], a[3]); SQRADD(a[2], a[2]); 46 | COMBA_STORE(b[4]); 47 | 48 | /* output 5 */ 49 | CARRY_FORWARD; 50 | SQRADDSC(a[0], a[5]); SQRADDAC(a[1], a[4]); SQRADDAC(a[2], a[3]); SQRADDDB; 51 | COMBA_STORE(b[5]); 52 | 53 | /* output 6 */ 54 | CARRY_FORWARD; 55 | SQRADDSC(a[0], a[6]); SQRADDAC(a[1], a[5]); SQRADDAC(a[2], a[4]); SQRADDDB; SQRADD(a[3], a[3]); 56 | COMBA_STORE(b[6]); 57 | 58 | /* output 7 */ 59 | CARRY_FORWARD; 60 | SQRADDSC(a[0], a[7]); SQRADDAC(a[1], a[6]); SQRADDAC(a[2], a[5]); SQRADDAC(a[3], a[4]); SQRADDDB; 61 | COMBA_STORE(b[7]); 62 | 63 | /* output 8 */ 64 | CARRY_FORWARD; 65 | SQRADDSC(a[1], a[7]); SQRADDAC(a[2], a[6]); SQRADDAC(a[3], a[5]); SQRADDDB; SQRADD(a[4], a[4]); 66 | COMBA_STORE(b[8]); 67 | 68 | /* output 9 */ 69 | CARRY_FORWARD; 70 | SQRADDSC(a[2], a[7]); SQRADDAC(a[3], a[6]); SQRADDAC(a[4], a[5]); SQRADDDB; 71 | COMBA_STORE(b[9]); 72 | 73 | /* output 10 */ 74 | CARRY_FORWARD; 75 | SQRADD2(a[3], a[7]); SQRADD2(a[4], a[6]); SQRADD(a[5], a[5]); 76 | COMBA_STORE(b[10]); 77 | 78 | /* output 11 */ 79 | CARRY_FORWARD; 80 | SQRADD2(a[4], a[7]); SQRADD2(a[5], a[6]); 81 | COMBA_STORE(b[11]); 82 | 83 | /* output 12 */ 84 | CARRY_FORWARD; 85 | SQRADD2(a[5], a[7]); SQRADD(a[6], a[6]); 86 | COMBA_STORE(b[12]); 87 | 88 | /* output 13 */ 89 | CARRY_FORWARD; 90 | SQRADD2(a[6], a[7]); 91 | COMBA_STORE(b[13]); 92 | 93 | /* output 14 */ 94 | CARRY_FORWARD; 95 | SQRADD(a[7], a[7]); 96 | COMBA_STORE(b[14]); 97 | COMBA_STORE2(b[15]); 98 | COMBA_FINI; 99 | 100 | B->used = 16; 101 | B->sign = FP_ZPOS; 102 | memcpy(B->dp, b, 16 * sizeof(fp_digit)); 103 | fp_clamp(B); 104 | } 105 | #endif 106 | -------------------------------------------------------------------------------- /src/sqr/fp_sqr_comba_9.c: -------------------------------------------------------------------------------- 1 | /* TomsFastMath, a fast ISO C bignum library. -- Tom St Denis */ 2 | /* SPDX-License-Identifier: Unlicense */ 3 | #ifndef TFM_PRE_GEN_MPI_C 4 | #define TFM_DEFINES 5 | #include "fp_sqr_comba.c" 6 | #endif 7 | 8 | #if defined(TFM_SQR9) && FP_SIZE >= 18 9 | void fp_sqr_comba9(const fp_int *A, fp_int *B) 10 | { 11 | const fp_digit *a; 12 | fp_digit b[18], c0, c1, c2; 13 | fp_digit sc0, sc1, sc2; 14 | #ifdef TFM_ISO 15 | fp_word tt; 16 | #endif 17 | 18 | a = A->dp; 19 | COMBA_START; 20 | 21 | /* clear carries */ 22 | CLEAR_CARRY; 23 | 24 | /* output 0 */ 25 | SQRADD(a[0],a[0]); 26 | COMBA_STORE(b[0]); 27 | 28 | /* output 1 */ 29 | CARRY_FORWARD; 30 | SQRADD2(a[0], a[1]); 31 | COMBA_STORE(b[1]); 32 | 33 | /* output 2 */ 34 | CARRY_FORWARD; 35 | SQRADD2(a[0], a[2]); SQRADD(a[1], a[1]); 36 | COMBA_STORE(b[2]); 37 | 38 | /* output 3 */ 39 | CARRY_FORWARD; 40 | SQRADD2(a[0], a[3]); SQRADD2(a[1], a[2]); 41 | COMBA_STORE(b[3]); 42 | 43 | /* output 4 */ 44 | CARRY_FORWARD; 45 | SQRADD2(a[0], a[4]); SQRADD2(a[1], a[3]); SQRADD(a[2], a[2]); 46 | COMBA_STORE(b[4]); 47 | 48 | /* output 5 */ 49 | CARRY_FORWARD; 50 | SQRADDSC(a[0], a[5]); SQRADDAC(a[1], a[4]); SQRADDAC(a[2], a[3]); SQRADDDB; 51 | COMBA_STORE(b[5]); 52 | 53 | /* output 6 */ 54 | CARRY_FORWARD; 55 | SQRADDSC(a[0], a[6]); SQRADDAC(a[1], a[5]); SQRADDAC(a[2], a[4]); SQRADDDB; SQRADD(a[3], a[3]); 56 | COMBA_STORE(b[6]); 57 | 58 | /* output 7 */ 59 | CARRY_FORWARD; 60 | SQRADDSC(a[0], a[7]); SQRADDAC(a[1], a[6]); SQRADDAC(a[2], a[5]); SQRADDAC(a[3], a[4]); SQRADDDB; 61 | COMBA_STORE(b[7]); 62 | 63 | /* output 8 */ 64 | CARRY_FORWARD; 65 | SQRADDSC(a[0], a[8]); SQRADDAC(a[1], a[7]); SQRADDAC(a[2], a[6]); SQRADDAC(a[3], a[5]); SQRADDDB; SQRADD(a[4], a[4]); 66 | COMBA_STORE(b[8]); 67 | 68 | /* output 9 */ 69 | CARRY_FORWARD; 70 | SQRADDSC(a[1], a[8]); SQRADDAC(a[2], a[7]); SQRADDAC(a[3], a[6]); SQRADDAC(a[4], a[5]); SQRADDDB; 71 | COMBA_STORE(b[9]); 72 | 73 | /* output 10 */ 74 | CARRY_FORWARD; 75 | SQRADDSC(a[2], a[8]); SQRADDAC(a[3], a[7]); SQRADDAC(a[4], a[6]); SQRADDDB; SQRADD(a[5], a[5]); 76 | COMBA_STORE(b[10]); 77 | 78 | /* output 11 */ 79 | CARRY_FORWARD; 80 | SQRADDSC(a[3], a[8]); SQRADDAC(a[4], a[7]); SQRADDAC(a[5], a[6]); SQRADDDB; 81 | COMBA_STORE(b[11]); 82 | 83 | /* output 12 */ 84 | CARRY_FORWARD; 85 | SQRADD2(a[4], a[8]); SQRADD2(a[5], a[7]); SQRADD(a[6], a[6]); 86 | COMBA_STORE(b[12]); 87 | 88 | /* output 13 */ 89 | CARRY_FORWARD; 90 | SQRADD2(a[5], a[8]); SQRADD2(a[6], a[7]); 91 | COMBA_STORE(b[13]); 92 | 93 | /* output 14 */ 94 | CARRY_FORWARD; 95 | SQRADD2(a[6], a[8]); SQRADD(a[7], a[7]); 96 | COMBA_STORE(b[14]); 97 | 98 | /* output 15 */ 99 | CARRY_FORWARD; 100 | SQRADD2(a[7], a[8]); 101 | COMBA_STORE(b[15]); 102 | 103 | /* output 16 */ 104 | CARRY_FORWARD; 105 | SQRADD(a[8], a[8]); 106 | COMBA_STORE(b[16]); 107 | COMBA_STORE2(b[17]); 108 | COMBA_FINI; 109 | 110 | B->used = 18; 111 | B->sign = FP_ZPOS; 112 | memcpy(B->dp, b, 18 * sizeof(fp_digit)); 113 | fp_clamp(B); 114 | } 115 | #endif 116 | -------------------------------------------------------------------------------- /src/sqr/fp_sqr_comba_generic.c: -------------------------------------------------------------------------------- 1 | /* TomsFastMath, a fast ISO C bignum library. -- Tom St Denis */ 2 | /* SPDX-License-Identifier: Unlicense */ 3 | 4 | #ifndef TFM_PRE_GEN_MPI_C 5 | #define TFM_DEFINES 6 | #include "fp_sqr_comba.c" 7 | #endif 8 | 9 | /* generic comba squarer */ 10 | void fp_sqr_comba(const fp_int *A, fp_int *B) 11 | { 12 | int pa, ix, iz; 13 | fp_digit c0, c1, c2; 14 | fp_int tmp, *dst; 15 | #ifdef TFM_ISO 16 | fp_word tt; 17 | #endif 18 | 19 | /* get size of output and trim */ 20 | pa = A->used + A->used; 21 | if (pa >= FP_SIZE) { 22 | pa = FP_SIZE-1; 23 | } 24 | 25 | /* number of output digits to produce */ 26 | COMBA_START; 27 | CLEAR_CARRY; 28 | 29 | if (A == B) { 30 | fp_zero(&tmp); 31 | dst = &tmp; 32 | } else { 33 | fp_zero(B); 34 | dst = B; 35 | } 36 | 37 | for (ix = 0; ix < pa; ix++) { 38 | int tx, ty, iy; 39 | const fp_digit *tmpy, *tmpx; 40 | 41 | /* get offsets into the two bignums */ 42 | ty = MIN(A->used-1, ix); 43 | tx = ix - ty; 44 | 45 | /* setup temp aliases */ 46 | tmpx = A->dp + tx; 47 | tmpy = A->dp + ty; 48 | 49 | /* this is the number of times the loop will iterrate, 50 | while (tx++ < a->used && ty-- >= 0) { ... } 51 | */ 52 | iy = MIN(A->used-tx, ty+1); 53 | 54 | /* now for squaring tx can never equal ty 55 | * we halve the distance since they approach 56 | * at a rate of 2x and we have to round because 57 | * odd cases need to be executed 58 | */ 59 | iy = MIN(iy, (ty-tx+1)>>1); 60 | 61 | /* forward carries */ 62 | CARRY_FORWARD; 63 | 64 | /* execute loop */ 65 | for (iz = 0; iz < iy; iz++) { 66 | fp_digit _tmpx = *tmpx++; 67 | fp_digit _tmpy = *tmpy--; 68 | SQRADD2(_tmpx, _tmpy); 69 | } 70 | 71 | /* even columns have the square term in them */ 72 | if ((ix&1) == 0) { 73 | fp_digit _a_dp = A->dp[ix>>1]; 74 | SQRADD(_a_dp, A->dp[ix>>1]); 75 | } 76 | 77 | /* store it */ 78 | COMBA_STORE(dst->dp[ix]); 79 | } 80 | 81 | COMBA_FINI; 82 | 83 | /* setup dest */ 84 | dst->used = pa; 85 | fp_clamp (dst); 86 | if (dst != B) { 87 | fp_copy(dst, B); 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /src/sqr/fp_sqrmod.c: -------------------------------------------------------------------------------- 1 | /* TomsFastMath, a fast ISO C bignum library. -- Tom St Denis */ 2 | /* SPDX-License-Identifier: Unlicense */ 3 | #include 4 | 5 | /* c = a * a (mod b) */ 6 | int fp_sqrmod(const fp_int *a, const fp_int *b, fp_int *c) 7 | { 8 | fp_int tmp; 9 | fp_zero(&tmp); 10 | fp_sqr(a, &tmp); 11 | return fp_mod(&tmp, b, c); 12 | } 13 | -------------------------------------------------------------------------------- /testme.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e 2 | # 3 | # Can be run with e.g. ./testme.sh "gcc-4.8 gcc-4.9", defaults to ./testme.sh "gcc" 4 | # 5 | # SPDX-License-Identifier: Unlicense 6 | 7 | _runtest() 8 | { 9 | echo -n "Run test $1 $2" 10 | trap 'echo " - build not successful, errors are:" && cat test_gcc_errors.txt' INT TERM EXIT 11 | make clean > /dev/null 12 | CC="${1}" make test_standalone -j9 $2 > /dev/null 2>test_gcc_errors.txt 13 | trap - INT TERM EXIT 14 | local outfile="test_$(echo ${1}${2} | tr -d '\"' | tr ' ' '_').txt" 15 | trap 'echo " - tests not successful, failed at:" && tail ${outfile}' INT TERM EXIT 16 | ./test > ${outfile} 17 | echo " successful" 18 | trap - INT TERM EXIT 19 | } 20 | 21 | gccopt="-m32 -m64 -mx32" 22 | if [ $# -ge 1 ] 23 | then 24 | gccver=$1 25 | else 26 | gccver="gcc" 27 | fi 28 | 29 | for gopt in ${gccopt}; 30 | do 31 | for gccv in ${gccver}; 32 | do 33 | _runtest "${gccv} ${gopt}" "-f makefile.shared" 34 | _runtest "${gccv} ${gopt}" "" 35 | done 36 | done 37 | 38 | -------------------------------------------------------------------------------- /tomsfastmath.pc.in: -------------------------------------------------------------------------------- 1 | # TomsFastMath, a fast ISO C bignum library. -- Tom St Denis 2 | # SPDX-License-Identifier: Unlicense 3 | 4 | prefix=@CMAKE_INSTALL_PREFIX@ 5 | libdir=${prefix}/@CMAKE_INSTALL_LIBDIR@ 6 | includedir=${prefix}/@CMAKE_INSTALL_INCLUDEDIR@/@PROJECT_NAME@ 7 | 8 | Name: TomFastMath 9 | Description: Fast multiple-precision integer library 10 | Version: @PROJECT_VERSION@ 11 | Libs: -L${libdir} -ltfm 12 | Cflags: -I${includedir} 13 | --------------------------------------------------------------------------------