├── .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: [](https://github.com/libtom/tomsfastmath/actions/workflows/main.yml)
11 |
12 | 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 | Processor | Size in bits | x86-32 | x86-64 | SSE2 | LTM |
33 | P4 | 512 | 8015598 | | 5895000 | 9884722 |
34 | | 1024 | 55559304 | | 39648730 | 59090432 |
35 | | 2048 | 409861746 | | 304110670 | 427456070 |
36 | Athlon Barton | 512 | 2289257 | | | 3909824 |
37 | | 1024 | 12871373 | | | 21175496 |
38 | | 2048 | 97211357 | | | 129845554 |
39 | Athlon64 | 512 | | 641743 | | 2183028 |
40 | | 1042 | | 3167406 | | 11900720 |
41 | | 2048 | | 20158609 | | 72376416 |
42 |
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 |
--------------------------------------------------------------------------------