diff --git a/bn_mp_decr.c b/bn_mp_decr.c
new file mode 100644
index 000000000..b57f5d099
--- /dev/null
+++ b/bn_mp_decr.c
@@ -0,0 +1,48 @@
+#include "tommath_private.h"
+#ifdef BN_MP_DECR_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * SPDX-License-Identifier: Unlicense
+ */
+
+
+/* Decrement "a" by one like "a--". Changes input! */
+int mp_decr(mp_int *a)
+{
+ int e = MP_OKAY;
+ if (IS_ZERO(a)) {
+ mp_set(a,1uL);
+ a->sign = MP_NEG;
+ return MP_OKAY;
+ } else if (a->sign == MP_NEG) {
+ a->sign = MP_ZPOS;
+ if ((e = mp_incr(a)) != MP_OKAY) {
+ return e;
+ }
+ /* There is no -0 in LTM */
+ if (!IS_ZERO(a)) {
+ a->sign = MP_NEG;
+ }
+ return MP_OKAY;
+ } else if (a->dp[0] > 1uL) {
+ a->dp[0]--;
+ if (a->dp[0] == 0) {
+ mp_zero(a);
+ }
+ return MP_OKAY;
+ }
+ return mp_sub_d(a, 1uL,a);
+}
+
+
+#endif
+/* ref: \$Format:\%D$ */
+/* git commit: \$Format:\%H$ */
+/* commit time: \$Format:\%ai$ */
diff --git a/bn_mp_incr.c b/bn_mp_incr.c
new file mode 100644
index 000000000..b7cd24a60
--- /dev/null
+++ b/bn_mp_incr.c
@@ -0,0 +1,42 @@
+#include "tommath_private.h"
+#ifdef BN_MP_INCR_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * SPDX-License-Identifier: Unlicense
+ */
+
+/* Increment "a" by one like "a++". Changes input! */
+int mp_incr(mp_int *a)
+{
+ int e = MP_OKAY;
+ if (IS_ZERO(a)) {
+ mp_set(a,1uL);
+ return MP_OKAY;
+ } else if (a->sign == MP_NEG) {
+ a->sign = MP_ZPOS;
+ if ((e = mp_decr(a)) != MP_OKAY) {
+ return e;
+ }
+ /* There is no -0 in LTM */
+ if (!IS_ZERO(a)) {
+ a->sign = MP_NEG;
+ }
+ return MP_OKAY;
+ } else if (a->dp[0] < MP_MASK) {
+ a->dp[0]++;
+ return MP_OKAY;
+ }
+ return mp_add_d(a, 1uL,a);
+}
+
+#endif
+/* ref: \$Format:\%D$ */
+/* git commit: \$Format:\%H$ */
+/* commit time: \$Format:\%ai$ */
diff --git a/callgraph.txt b/callgraph.txt
index 5ca1f98e8..afcfa0504 100644
--- a/callgraph.txt
+++ b/callgraph.txt
@@ -256,6 +256,23 @@ BN_MP_COPY_C
BN_MP_COUNT_BITS_C
+BN_MP_DECR_C
++--->BN_MP_SET_C
+| +--->BN_MP_ZERO_C
++--->BN_MP_INCR_C
+| +--->BN_MP_ADD_D_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_SUB_D_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CLAMP_C
++--->BN_MP_ZERO_C
++--->BN_MP_SUB_D_C
+| +--->BN_MP_GROW_C
+| +--->BN_MP_ADD_D_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_MP_CLAMP_C
+
+
BN_MP_DIV_2D_C
+--->BN_MP_COPY_C
| +--->BN_MP_GROW_C
@@ -2357,6 +2374,23 @@ BN_MP_IMPORT_C
+--->BN_MP_CLAMP_C
+BN_MP_INCR_C
++--->BN_MP_SET_C
+| +--->BN_MP_ZERO_C
++--->BN_MP_DECR_C
+| +--->BN_MP_ZERO_C
+| +--->BN_MP_SUB_D_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_ADD_D_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CLAMP_C
++--->BN_MP_ADD_D_C
+| +--->BN_MP_GROW_C
+| +--->BN_MP_SUB_D_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_MP_CLAMP_C
+
+
BN_MP_INIT_C
diff --git a/demo/test.c b/demo/test.c
index 751142c95..8d9fa32d0 100644
--- a/demo/test.c
+++ b/demo/test.c
@@ -1230,6 +1230,138 @@ static int test_mp_reduce_2k_l(void)
# endif /* LTM_DEMO_TEST_REDUCE_2K_L */
}
+static int test_mp_incr(void)
+{
+ mp_int a, b;
+ int e = MP_OKAY;
+
+ if ((e = mp_init_multi(&a, &b, NULL)) != MP_OKAY) {
+ goto LTM_ERR;
+ }
+
+ /* Does it increment inside the limits of a MP_xBIT limb? */
+ mp_set(&a, MP_MASK/2);
+ if ((e = mp_incr(&a)) != MP_OKAY) {
+ goto LTM_ERR;
+ }
+ if (mp_cmp_d(&a, (MP_MASK/2uL) + 1uL) != MP_EQ) {
+ goto LTM_ERR;
+ }
+
+ /* Does it increment outside of the limits of a MP_xBIT limb? */
+ mp_set(&a, MP_MASK);
+ mp_set(&b, MP_MASK);
+ if ((e = mp_incr(&a)) != MP_OKAY) {
+ goto LTM_ERR;
+ }
+ if ((e = mp_add_d(&b, 1uL, &b)) != MP_OKAY) {
+ goto LTM_ERR;
+ }
+ if (mp_cmp(&a, &b) != MP_EQ) {
+ goto LTM_ERR;
+ }
+
+ /* Does it increment from -1 to 0? */
+ mp_set(&a, 1uL);
+ a.sign = MP_NEG;
+ if ((e = mp_incr(&a)) != MP_OKAY) {
+ goto LTM_ERR;
+ }
+ if (mp_cmp_d(&a, 0uL) != MP_EQ) {
+ goto LTM_ERR;
+ }
+
+ /* Does it increment from -(MP_MASK + 1) to -MP_MASK? */
+ mp_set(&a, MP_MASK);
+ if ((e = mp_add_d(&a, 1uL, &a)) != MP_OKAY) {
+ goto LTM_ERR;
+ }
+ a.sign = MP_NEG;
+ if ((e = mp_incr(&a)) != MP_OKAY) {
+ goto LTM_ERR;
+ }
+ if (a.sign != MP_NEG) {
+ goto LTM_ERR;
+ }
+ a.sign = MP_ZPOS;
+ if (mp_cmp_d(&a, MP_MASK) != MP_EQ) {puts("DDD");
+ goto LTM_ERR;
+ }
+
+ mp_clear_multi(&a, &b, NULL);
+ return EXIT_SUCCESS;
+LTM_ERR:
+ mp_clear_multi(&a, &b, NULL);
+ return EXIT_FAILURE;
+}
+
+static int test_mp_decr(void)
+{
+ mp_int a, b;
+ int e = MP_OKAY;
+
+ if ((e = mp_init_multi(&a, &b, NULL)) != MP_OKAY) {
+ goto LTM_ERR;
+ }
+
+ /* Does it decrement inside the limits of a MP_xBIT limb? */
+ mp_set(&a, MP_MASK/2);
+ if ((e = mp_decr(&a)) != MP_OKAY) {
+ goto LTM_ERR;
+ }
+ if (mp_cmp_d(&a, (MP_MASK/2uL) - 1uL) != MP_EQ) {
+ goto LTM_ERR;
+ }
+
+ /* Does it decrement outside of the limits of a MP_xBIT limb? */
+ mp_set(&a, MP_MASK);
+ if ((e = mp_add_d(&a, 1uL, &a)) != MP_OKAY) {
+ goto LTM_ERR;
+ }
+ if ((e = mp_decr(&a)) != MP_OKAY) {
+ goto LTM_ERR;
+ }
+ if (mp_cmp_d(&a, MP_MASK) != MP_EQ) {
+ goto LTM_ERR;
+ }
+
+ /* Does it decrement from 0 to -1? */
+ mp_zero(&a);
+ if ((e = mp_decr(&a)) != MP_OKAY) {
+ goto LTM_ERR;
+ }
+ if (a.sign == MP_NEG) {
+ a.sign = MP_ZPOS;
+ if (mp_cmp_d(&a, 1uL) != MP_EQ) {
+ goto LTM_ERR;
+ }
+ } else {
+ goto LTM_ERR;
+ }
+
+
+ /* Does it decrement from -MP_MASK to -(MP_MASK + 1)? */
+ mp_set(&a, MP_MASK);
+ a.sign = MP_NEG;
+ mp_set(&b, MP_MASK);
+ b.sign = MP_NEG;
+ if ((e = mp_sub_d(&b, 1uL, &b)) != MP_OKAY) {
+ goto LTM_ERR;
+ }
+ if ((e = mp_decr(&a)) != MP_OKAY) {
+ goto LTM_ERR;
+ }
+ if (mp_cmp(&a, &b) != MP_EQ) {
+ goto LTM_ERR;
+ }
+
+ mp_clear_multi(&a, &b, NULL);
+ return EXIT_SUCCESS;
+LTM_ERR:
+ mp_clear_multi(&a, &b, NULL);
+ return EXIT_FAILURE;
+}
+
int unit_tests(void)
{
static const struct {
@@ -1262,6 +1394,8 @@ int unit_tests(void)
T(mp_tc_div_2d),
T(mp_tc_or),
T(mp_tc_xor),
+ T(mp_incr),
+ T(mp_decr)
#undef T
};
unsigned long i;
diff --git a/doc/bn.tex b/doc/bn.tex
index 533c623fb..2213b2da8 100644
--- a/doc/bn.tex
+++ b/doc/bn.tex
@@ -2284,6 +2284,12 @@ \section{Single Digit Functions}
functions fairly handy if you have to work with relatively small numbers since you will not have to allocate
an entire mp\_int to store a number like $1$ or $2$.
+The functions \texttt{mp\_incr} and \texttt{mp\_decr} mimic the postfix operators \texttt{++} and \texttt{--} respectively, to increment the input by one. They call the full single-digit functions if the addition would carry. Both functions need to be included in a minimized library because they call each other in case of a negative input, These functions change the inputs!
+\begin{alltt}
+int mp_incr(mp_int *a);
+int mp_decr(mp_int *a);
+\end{alltt}
+
The division by three can be made faster by replacing the division with a multiplication by the multiplicative inverse of three.
diff --git a/libtommath_VS2008.vcproj b/libtommath_VS2008.vcproj
index 060dd5941..ffb8a6497 100644
--- a/libtommath_VS2008.vcproj
+++ b/libtommath_VS2008.vcproj
@@ -400,6 +400,10 @@
RelativePath="bn_mp_count_bits.c"
>
+
+
@@ -500,6 +504,10 @@
RelativePath="bn_mp_import.c"
>
+
+
diff --git a/makefile b/makefile
index da89364b9..484222f90 100644
--- a/makefile
+++ b/makefile
@@ -29,17 +29,17 @@ LCOV_ARGS=--directory .
OBJECTS=bn_error.o bn_fast_mp_invmod.o bn_fast_mp_montgomery_reduce.o bn_fast_s_mp_mul_digs.o \
bn_fast_s_mp_mul_high_digs.o bn_fast_s_mp_sqr.o bn_mp_2expt.o bn_mp_abs.o bn_mp_add.o bn_mp_add_d.o \
bn_mp_addmod.o bn_mp_and.o bn_mp_clamp.o bn_mp_clear.o bn_mp_clear_multi.o bn_mp_cmp.o bn_mp_cmp_d.o \
-bn_mp_cmp_mag.o bn_mp_cnt_lsb.o bn_mp_complement.o bn_mp_copy.o bn_mp_count_bits.o bn_mp_div.o \
-bn_mp_div_2.o bn_mp_div_2d.o bn_mp_div_3.o bn_mp_div_d.o bn_mp_dr_is_modulus.o bn_mp_dr_reduce.o \
-bn_mp_dr_setup.o bn_mp_exch.o bn_mp_export.o bn_mp_expt_d.o bn_mp_expt_d_ex.o bn_mp_exptmod.o \
-bn_mp_exptmod_fast.o bn_mp_exteuclid.o bn_mp_fread.o bn_mp_fwrite.o bn_mp_gcd.o bn_mp_get_bit.o \
-bn_mp_get_double.o bn_mp_get_int.o bn_mp_get_long.o bn_mp_get_long_long.o bn_mp_grow.o bn_mp_import.o \
-bn_mp_init.o bn_mp_init_copy.o bn_mp_init_multi.o bn_mp_init_set.o bn_mp_init_set_int.o bn_mp_init_size.o \
-bn_mp_invmod.o bn_mp_invmod_slow.o bn_mp_is_square.o bn_mp_iseven.o bn_mp_isodd.o bn_mp_jacobi.o \
-bn_mp_karatsuba_mul.o bn_mp_karatsuba_sqr.o bn_mp_kronecker.o bn_mp_lcm.o bn_mp_lshd.o bn_mp_mod.o \
-bn_mp_mod_2d.o bn_mp_mod_d.o bn_mp_montgomery_calc_normalization.o bn_mp_montgomery_reduce.o \
-bn_mp_montgomery_setup.o bn_mp_mul.o bn_mp_mul_2.o bn_mp_mul_2d.o bn_mp_mul_d.o bn_mp_mulmod.o \
-bn_mp_n_root.o bn_mp_n_root_ex.o bn_mp_neg.o bn_mp_or.o bn_mp_prime_fermat.o \
+bn_mp_cmp_mag.o bn_mp_cnt_lsb.o bn_mp_complement.o bn_mp_copy.o bn_mp_count_bits.o bn_mp_decr.o \
+bn_mp_div.o bn_mp_div_2.o bn_mp_div_2d.o bn_mp_div_3.o bn_mp_div_d.o bn_mp_dr_is_modulus.o \
+bn_mp_dr_reduce.o bn_mp_dr_setup.o bn_mp_exch.o bn_mp_export.o bn_mp_expt_d.o bn_mp_expt_d_ex.o \
+bn_mp_exptmod.o bn_mp_exptmod_fast.o bn_mp_exteuclid.o bn_mp_fread.o bn_mp_fwrite.o bn_mp_gcd.o \
+bn_mp_get_bit.o bn_mp_get_double.o bn_mp_get_int.o bn_mp_get_long.o bn_mp_get_long_long.o bn_mp_grow.o \
+bn_mp_import.o bn_mp_incr.o bn_mp_init.o bn_mp_init_copy.o bn_mp_init_multi.o bn_mp_init_set.o \
+bn_mp_init_set_int.o bn_mp_init_size.o bn_mp_invmod.o bn_mp_invmod_slow.o bn_mp_is_square.o \
+bn_mp_iseven.o bn_mp_isodd.o bn_mp_jacobi.o bn_mp_karatsuba_mul.o bn_mp_karatsuba_sqr.o bn_mp_kronecker.o \
+bn_mp_lcm.o bn_mp_lshd.o bn_mp_mod.o bn_mp_mod_2d.o bn_mp_mod_d.o bn_mp_montgomery_calc_normalization.o \
+bn_mp_montgomery_reduce.o bn_mp_montgomery_setup.o bn_mp_mul.o bn_mp_mul_2.o bn_mp_mul_2d.o bn_mp_mul_d.o \
+bn_mp_mulmod.o bn_mp_n_root.o bn_mp_n_root_ex.o bn_mp_neg.o bn_mp_or.o bn_mp_prime_fermat.o \
bn_mp_prime_frobenius_underwood.o bn_mp_prime_is_divisible.o bn_mp_prime_is_prime.o \
bn_mp_prime_miller_rabin.o bn_mp_prime_next_prime.o bn_mp_prime_rabin_miller_trials.o \
bn_mp_prime_random_ex.o bn_mp_prime_strong_lucas_selfridge.o bn_mp_radix_size.o bn_mp_radix_smap.o \
diff --git a/makefile.mingw b/makefile.mingw
index 5ad880a09..5a176cded 100644
--- a/makefile.mingw
+++ b/makefile.mingw
@@ -32,17 +32,17 @@ LIBMAIN_D =libtommath.dll
OBJECTS=bn_error.o bn_fast_mp_invmod.o bn_fast_mp_montgomery_reduce.o bn_fast_s_mp_mul_digs.o \
bn_fast_s_mp_mul_high_digs.o bn_fast_s_mp_sqr.o bn_mp_2expt.o bn_mp_abs.o bn_mp_add.o bn_mp_add_d.o \
bn_mp_addmod.o bn_mp_and.o bn_mp_clamp.o bn_mp_clear.o bn_mp_clear_multi.o bn_mp_cmp.o bn_mp_cmp_d.o \
-bn_mp_cmp_mag.o bn_mp_cnt_lsb.o bn_mp_complement.o bn_mp_copy.o bn_mp_count_bits.o bn_mp_div.o \
-bn_mp_div_2.o bn_mp_div_2d.o bn_mp_div_3.o bn_mp_div_d.o bn_mp_dr_is_modulus.o bn_mp_dr_reduce.o \
-bn_mp_dr_setup.o bn_mp_exch.o bn_mp_export.o bn_mp_expt_d.o bn_mp_expt_d_ex.o bn_mp_exptmod.o \
-bn_mp_exptmod_fast.o bn_mp_exteuclid.o bn_mp_fread.o bn_mp_fwrite.o bn_mp_gcd.o bn_mp_get_bit.o \
-bn_mp_get_double.o bn_mp_get_int.o bn_mp_get_long.o bn_mp_get_long_long.o bn_mp_grow.o bn_mp_import.o \
-bn_mp_init.o bn_mp_init_copy.o bn_mp_init_multi.o bn_mp_init_set.o bn_mp_init_set_int.o bn_mp_init_size.o \
-bn_mp_invmod.o bn_mp_invmod_slow.o bn_mp_is_square.o bn_mp_iseven.o bn_mp_isodd.o bn_mp_jacobi.o \
-bn_mp_karatsuba_mul.o bn_mp_karatsuba_sqr.o bn_mp_kronecker.o bn_mp_lcm.o bn_mp_lshd.o bn_mp_mod.o \
-bn_mp_mod_2d.o bn_mp_mod_d.o bn_mp_montgomery_calc_normalization.o bn_mp_montgomery_reduce.o \
-bn_mp_montgomery_setup.o bn_mp_mul.o bn_mp_mul_2.o bn_mp_mul_2d.o bn_mp_mul_d.o bn_mp_mulmod.o \
-bn_mp_n_root.o bn_mp_n_root_ex.o bn_mp_neg.o bn_mp_or.o bn_mp_prime_fermat.o \
+bn_mp_cmp_mag.o bn_mp_cnt_lsb.o bn_mp_complement.o bn_mp_copy.o bn_mp_count_bits.o bn_mp_decr.o \
+bn_mp_div.o bn_mp_div_2.o bn_mp_div_2d.o bn_mp_div_3.o bn_mp_div_d.o bn_mp_dr_is_modulus.o \
+bn_mp_dr_reduce.o bn_mp_dr_setup.o bn_mp_exch.o bn_mp_export.o bn_mp_expt_d.o bn_mp_expt_d_ex.o \
+bn_mp_exptmod.o bn_mp_exptmod_fast.o bn_mp_exteuclid.o bn_mp_fread.o bn_mp_fwrite.o bn_mp_gcd.o \
+bn_mp_get_bit.o bn_mp_get_double.o bn_mp_get_int.o bn_mp_get_long.o bn_mp_get_long_long.o bn_mp_grow.o \
+bn_mp_import.o bn_mp_incr.o bn_mp_init.o bn_mp_init_copy.o bn_mp_init_multi.o bn_mp_init_set.o \
+bn_mp_init_set_int.o bn_mp_init_size.o bn_mp_invmod.o bn_mp_invmod_slow.o bn_mp_is_square.o \
+bn_mp_iseven.o bn_mp_isodd.o bn_mp_jacobi.o bn_mp_karatsuba_mul.o bn_mp_karatsuba_sqr.o bn_mp_kronecker.o \
+bn_mp_lcm.o bn_mp_lshd.o bn_mp_mod.o bn_mp_mod_2d.o bn_mp_mod_d.o bn_mp_montgomery_calc_normalization.o \
+bn_mp_montgomery_reduce.o bn_mp_montgomery_setup.o bn_mp_mul.o bn_mp_mul_2.o bn_mp_mul_2d.o bn_mp_mul_d.o \
+bn_mp_mulmod.o bn_mp_n_root.o bn_mp_n_root_ex.o bn_mp_neg.o bn_mp_or.o bn_mp_prime_fermat.o \
bn_mp_prime_frobenius_underwood.o bn_mp_prime_is_divisible.o bn_mp_prime_is_prime.o \
bn_mp_prime_miller_rabin.o bn_mp_prime_next_prime.o bn_mp_prime_rabin_miller_trials.o \
bn_mp_prime_random_ex.o bn_mp_prime_strong_lucas_selfridge.o bn_mp_radix_size.o bn_mp_radix_smap.o \
diff --git a/makefile.msvc b/makefile.msvc
index 12d571a2e..3851bdb67 100644
--- a/makefile.msvc
+++ b/makefile.msvc
@@ -24,17 +24,17 @@ LIBMAIN_S =tommath.lib
OBJECTS=bn_error.obj bn_fast_mp_invmod.obj bn_fast_mp_montgomery_reduce.obj bn_fast_s_mp_mul_digs.obj \
bn_fast_s_mp_mul_high_digs.obj bn_fast_s_mp_sqr.obj bn_mp_2expt.obj bn_mp_abs.obj bn_mp_add.obj bn_mp_add_d.obj \
bn_mp_addmod.obj bn_mp_and.obj bn_mp_clamp.obj bn_mp_clear.obj bn_mp_clear_multi.obj bn_mp_cmp.obj bn_mp_cmp_d.obj \
-bn_mp_cmp_mag.obj bn_mp_cnt_lsb.obj bn_mp_complement.obj bn_mp_copy.obj bn_mp_count_bits.obj bn_mp_div.obj \
-bn_mp_div_2.obj bn_mp_div_2d.obj bn_mp_div_3.obj bn_mp_div_d.obj bn_mp_dr_is_modulus.obj bn_mp_dr_reduce.obj \
-bn_mp_dr_setup.obj bn_mp_exch.obj bn_mp_export.obj bn_mp_expt_d.obj bn_mp_expt_d_ex.obj bn_mp_exptmod.obj \
-bn_mp_exptmod_fast.obj bn_mp_exteuclid.obj bn_mp_fread.obj bn_mp_fwrite.obj bn_mp_gcd.obj bn_mp_get_bit.obj \
-bn_mp_get_double.obj bn_mp_get_int.obj bn_mp_get_long.obj bn_mp_get_long_long.obj bn_mp_grow.obj bn_mp_import.obj \
-bn_mp_init.obj bn_mp_init_copy.obj bn_mp_init_multi.obj bn_mp_init_set.obj bn_mp_init_set_int.obj bn_mp_init_size.obj \
-bn_mp_invmod.obj bn_mp_invmod_slow.obj bn_mp_is_square.obj bn_mp_iseven.obj bn_mp_isodd.obj bn_mp_jacobi.obj \
-bn_mp_karatsuba_mul.obj bn_mp_karatsuba_sqr.obj bn_mp_kronecker.obj bn_mp_lcm.obj bn_mp_lshd.obj bn_mp_mod.obj \
-bn_mp_mod_2d.obj bn_mp_mod_d.obj bn_mp_montgomery_calc_normalization.obj bn_mp_montgomery_reduce.obj \
-bn_mp_montgomery_setup.obj bn_mp_mul.obj bn_mp_mul_2.obj bn_mp_mul_2d.obj bn_mp_mul_d.obj bn_mp_mulmod.obj \
-bn_mp_n_root.obj bn_mp_n_root_ex.obj bn_mp_neg.obj bn_mp_or.obj bn_mp_prime_fermat.obj \
+bn_mp_cmp_mag.obj bn_mp_cnt_lsb.obj bn_mp_complement.obj bn_mp_copy.obj bn_mp_count_bits.obj bn_mp_decr.obj \
+bn_mp_div.obj bn_mp_div_2.obj bn_mp_div_2d.obj bn_mp_div_3.obj bn_mp_div_d.obj bn_mp_dr_is_modulus.obj \
+bn_mp_dr_reduce.obj bn_mp_dr_setup.obj bn_mp_exch.obj bn_mp_export.obj bn_mp_expt_d.obj bn_mp_expt_d_ex.obj \
+bn_mp_exptmod.obj bn_mp_exptmod_fast.obj bn_mp_exteuclid.obj bn_mp_fread.obj bn_mp_fwrite.obj bn_mp_gcd.obj \
+bn_mp_get_bit.obj bn_mp_get_double.obj bn_mp_get_int.obj bn_mp_get_long.obj bn_mp_get_long_long.obj bn_mp_grow.obj \
+bn_mp_import.obj bn_mp_incr.obj bn_mp_init.obj bn_mp_init_copy.obj bn_mp_init_multi.obj bn_mp_init_set.obj \
+bn_mp_init_set_int.obj bn_mp_init_size.obj bn_mp_invmod.obj bn_mp_invmod_slow.obj bn_mp_is_square.obj \
+bn_mp_iseven.obj bn_mp_isodd.obj bn_mp_jacobi.obj bn_mp_karatsuba_mul.obj bn_mp_karatsuba_sqr.obj bn_mp_kronecker.obj \
+bn_mp_lcm.obj bn_mp_lshd.obj bn_mp_mod.obj bn_mp_mod_2d.obj bn_mp_mod_d.obj bn_mp_montgomery_calc_normalization.obj \
+bn_mp_montgomery_reduce.obj bn_mp_montgomery_setup.obj bn_mp_mul.obj bn_mp_mul_2.obj bn_mp_mul_2d.obj bn_mp_mul_d.obj \
+bn_mp_mulmod.obj bn_mp_n_root.obj bn_mp_n_root_ex.obj bn_mp_neg.obj bn_mp_or.obj bn_mp_prime_fermat.obj \
bn_mp_prime_frobenius_underwood.obj bn_mp_prime_is_divisible.obj bn_mp_prime_is_prime.obj \
bn_mp_prime_miller_rabin.obj bn_mp_prime_next_prime.obj bn_mp_prime_rabin_miller_trials.obj \
bn_mp_prime_random_ex.obj bn_mp_prime_strong_lucas_selfridge.obj bn_mp_radix_size.obj bn_mp_radix_smap.obj \
diff --git a/makefile.shared b/makefile.shared
index ac9bad04f..2703feec3 100644
--- a/makefile.shared
+++ b/makefile.shared
@@ -26,17 +26,17 @@ LCOV_ARGS=--directory .libs --directory .
OBJECTS=bn_error.o bn_fast_mp_invmod.o bn_fast_mp_montgomery_reduce.o bn_fast_s_mp_mul_digs.o \
bn_fast_s_mp_mul_high_digs.o bn_fast_s_mp_sqr.o bn_mp_2expt.o bn_mp_abs.o bn_mp_add.o bn_mp_add_d.o \
bn_mp_addmod.o bn_mp_and.o bn_mp_clamp.o bn_mp_clear.o bn_mp_clear_multi.o bn_mp_cmp.o bn_mp_cmp_d.o \
-bn_mp_cmp_mag.o bn_mp_cnt_lsb.o bn_mp_complement.o bn_mp_copy.o bn_mp_count_bits.o bn_mp_div.o \
-bn_mp_div_2.o bn_mp_div_2d.o bn_mp_div_3.o bn_mp_div_d.o bn_mp_dr_is_modulus.o bn_mp_dr_reduce.o \
-bn_mp_dr_setup.o bn_mp_exch.o bn_mp_export.o bn_mp_expt_d.o bn_mp_expt_d_ex.o bn_mp_exptmod.o \
-bn_mp_exptmod_fast.o bn_mp_exteuclid.o bn_mp_fread.o bn_mp_fwrite.o bn_mp_gcd.o bn_mp_get_bit.o \
-bn_mp_get_double.o bn_mp_get_int.o bn_mp_get_long.o bn_mp_get_long_long.o bn_mp_grow.o bn_mp_import.o \
-bn_mp_init.o bn_mp_init_copy.o bn_mp_init_multi.o bn_mp_init_set.o bn_mp_init_set_int.o bn_mp_init_size.o \
-bn_mp_invmod.o bn_mp_invmod_slow.o bn_mp_is_square.o bn_mp_iseven.o bn_mp_isodd.o bn_mp_jacobi.o \
-bn_mp_karatsuba_mul.o bn_mp_karatsuba_sqr.o bn_mp_kronecker.o bn_mp_lcm.o bn_mp_lshd.o bn_mp_mod.o \
-bn_mp_mod_2d.o bn_mp_mod_d.o bn_mp_montgomery_calc_normalization.o bn_mp_montgomery_reduce.o \
-bn_mp_montgomery_setup.o bn_mp_mul.o bn_mp_mul_2.o bn_mp_mul_2d.o bn_mp_mul_d.o bn_mp_mulmod.o \
-bn_mp_n_root.o bn_mp_n_root_ex.o bn_mp_neg.o bn_mp_or.o bn_mp_prime_fermat.o \
+bn_mp_cmp_mag.o bn_mp_cnt_lsb.o bn_mp_complement.o bn_mp_copy.o bn_mp_count_bits.o bn_mp_decr.o \
+bn_mp_div.o bn_mp_div_2.o bn_mp_div_2d.o bn_mp_div_3.o bn_mp_div_d.o bn_mp_dr_is_modulus.o \
+bn_mp_dr_reduce.o bn_mp_dr_setup.o bn_mp_exch.o bn_mp_export.o bn_mp_expt_d.o bn_mp_expt_d_ex.o \
+bn_mp_exptmod.o bn_mp_exptmod_fast.o bn_mp_exteuclid.o bn_mp_fread.o bn_mp_fwrite.o bn_mp_gcd.o \
+bn_mp_get_bit.o bn_mp_get_double.o bn_mp_get_int.o bn_mp_get_long.o bn_mp_get_long_long.o bn_mp_grow.o \
+bn_mp_import.o bn_mp_incr.o bn_mp_init.o bn_mp_init_copy.o bn_mp_init_multi.o bn_mp_init_set.o \
+bn_mp_init_set_int.o bn_mp_init_size.o bn_mp_invmod.o bn_mp_invmod_slow.o bn_mp_is_square.o \
+bn_mp_iseven.o bn_mp_isodd.o bn_mp_jacobi.o bn_mp_karatsuba_mul.o bn_mp_karatsuba_sqr.o bn_mp_kronecker.o \
+bn_mp_lcm.o bn_mp_lshd.o bn_mp_mod.o bn_mp_mod_2d.o bn_mp_mod_d.o bn_mp_montgomery_calc_normalization.o \
+bn_mp_montgomery_reduce.o bn_mp_montgomery_setup.o bn_mp_mul.o bn_mp_mul_2.o bn_mp_mul_2d.o bn_mp_mul_d.o \
+bn_mp_mulmod.o bn_mp_n_root.o bn_mp_n_root_ex.o bn_mp_neg.o bn_mp_or.o bn_mp_prime_fermat.o \
bn_mp_prime_frobenius_underwood.o bn_mp_prime_is_divisible.o bn_mp_prime_is_prime.o \
bn_mp_prime_miller_rabin.o bn_mp_prime_next_prime.o bn_mp_prime_rabin_miller_trials.o \
bn_mp_prime_random_ex.o bn_mp_prime_strong_lucas_selfridge.o bn_mp_radix_size.o bn_mp_radix_smap.o \
diff --git a/makefile.unix b/makefile.unix
index 6c34ec6fb..0ab79743b 100644
--- a/makefile.unix
+++ b/makefile.unix
@@ -33,17 +33,17 @@ LIBMAIN_S = libtommath.a
OBJECTS=bn_error.o bn_fast_mp_invmod.o bn_fast_mp_montgomery_reduce.o bn_fast_s_mp_mul_digs.o \
bn_fast_s_mp_mul_high_digs.o bn_fast_s_mp_sqr.o bn_mp_2expt.o bn_mp_abs.o bn_mp_add.o bn_mp_add_d.o \
bn_mp_addmod.o bn_mp_and.o bn_mp_clamp.o bn_mp_clear.o bn_mp_clear_multi.o bn_mp_cmp.o bn_mp_cmp_d.o \
-bn_mp_cmp_mag.o bn_mp_cnt_lsb.o bn_mp_complement.o bn_mp_copy.o bn_mp_count_bits.o bn_mp_div.o \
-bn_mp_div_2.o bn_mp_div_2d.o bn_mp_div_3.o bn_mp_div_d.o bn_mp_dr_is_modulus.o bn_mp_dr_reduce.o \
-bn_mp_dr_setup.o bn_mp_exch.o bn_mp_export.o bn_mp_expt_d.o bn_mp_expt_d_ex.o bn_mp_exptmod.o \
-bn_mp_exptmod_fast.o bn_mp_exteuclid.o bn_mp_fread.o bn_mp_fwrite.o bn_mp_gcd.o bn_mp_get_bit.o \
-bn_mp_get_double.o bn_mp_get_int.o bn_mp_get_long.o bn_mp_get_long_long.o bn_mp_grow.o bn_mp_import.o \
-bn_mp_init.o bn_mp_init_copy.o bn_mp_init_multi.o bn_mp_init_set.o bn_mp_init_set_int.o bn_mp_init_size.o \
-bn_mp_invmod.o bn_mp_invmod_slow.o bn_mp_is_square.o bn_mp_iseven.o bn_mp_isodd.o bn_mp_jacobi.o \
-bn_mp_karatsuba_mul.o bn_mp_karatsuba_sqr.o bn_mp_kronecker.o bn_mp_lcm.o bn_mp_lshd.o bn_mp_mod.o \
-bn_mp_mod_2d.o bn_mp_mod_d.o bn_mp_montgomery_calc_normalization.o bn_mp_montgomery_reduce.o \
-bn_mp_montgomery_setup.o bn_mp_mul.o bn_mp_mul_2.o bn_mp_mul_2d.o bn_mp_mul_d.o bn_mp_mulmod.o \
-bn_mp_n_root.o bn_mp_n_root_ex.o bn_mp_neg.o bn_mp_or.o bn_mp_prime_fermat.o \
+bn_mp_cmp_mag.o bn_mp_cnt_lsb.o bn_mp_complement.o bn_mp_copy.o bn_mp_count_bits.o bn_mp_decr.o \
+bn_mp_div.o bn_mp_div_2.o bn_mp_div_2d.o bn_mp_div_3.o bn_mp_div_d.o bn_mp_dr_is_modulus.o \
+bn_mp_dr_reduce.o bn_mp_dr_setup.o bn_mp_exch.o bn_mp_export.o bn_mp_expt_d.o bn_mp_expt_d_ex.o \
+bn_mp_exptmod.o bn_mp_exptmod_fast.o bn_mp_exteuclid.o bn_mp_fread.o bn_mp_fwrite.o bn_mp_gcd.o \
+bn_mp_get_bit.o bn_mp_get_double.o bn_mp_get_int.o bn_mp_get_long.o bn_mp_get_long_long.o bn_mp_grow.o \
+bn_mp_import.o bn_mp_incr.o bn_mp_init.o bn_mp_init_copy.o bn_mp_init_multi.o bn_mp_init_set.o \
+bn_mp_init_set_int.o bn_mp_init_size.o bn_mp_invmod.o bn_mp_invmod_slow.o bn_mp_is_square.o \
+bn_mp_iseven.o bn_mp_isodd.o bn_mp_jacobi.o bn_mp_karatsuba_mul.o bn_mp_karatsuba_sqr.o bn_mp_kronecker.o \
+bn_mp_lcm.o bn_mp_lshd.o bn_mp_mod.o bn_mp_mod_2d.o bn_mp_mod_d.o bn_mp_montgomery_calc_normalization.o \
+bn_mp_montgomery_reduce.o bn_mp_montgomery_setup.o bn_mp_mul.o bn_mp_mul_2.o bn_mp_mul_2d.o bn_mp_mul_d.o \
+bn_mp_mulmod.o bn_mp_n_root.o bn_mp_n_root_ex.o bn_mp_neg.o bn_mp_or.o bn_mp_prime_fermat.o \
bn_mp_prime_frobenius_underwood.o bn_mp_prime_is_divisible.o bn_mp_prime_is_prime.o \
bn_mp_prime_miller_rabin.o bn_mp_prime_next_prime.o bn_mp_prime_rabin_miller_trials.o \
bn_mp_prime_random_ex.o bn_mp_prime_strong_lucas_selfridge.o bn_mp_radix_size.o bn_mp_radix_smap.o \
diff --git a/tommath.h b/tommath.h
index 692433b1b..e22562662 100644
--- a/tommath.h
+++ b/tommath.h
@@ -361,9 +361,15 @@ int mp_cmp_d(const mp_int *a, mp_digit b);
/* c = a + b */
int mp_add_d(const mp_int *a, mp_digit b, mp_int *c);
+/* Increment "a" by one like "a++". Changes input! */
+int mp_incr(mp_int *a);
+
/* c = a - b */
int mp_sub_d(const mp_int *a, mp_digit b, mp_int *c);
+/* Decrement "a" by one like "a--". Changes input! */
+int mp_decr(mp_int *a);
+
/* c = a * b */
int mp_mul_d(const mp_int *a, mp_digit b, mp_int *c);
diff --git a/tommath_class.h b/tommath_class.h
index 69c6a2aea..84fbd5368 100644
--- a/tommath_class.h
+++ b/tommath_class.h
@@ -41,6 +41,7 @@
# define BN_MP_COMPLEMENT_C
# define BN_MP_COPY_C
# define BN_MP_COUNT_BITS_C
+# define BN_MP_DECR_C
# define BN_MP_DIV_C
# define BN_MP_DIV_2_C
# define BN_MP_DIV_2D_C
@@ -66,6 +67,7 @@
# define BN_MP_GET_LONG_LONG_C
# define BN_MP_GROW_C
# define BN_MP_IMPORT_C
+# define BN_MP_INCR_C
# define BN_MP_INIT_C
# define BN_MP_INIT_COPY_C
# define BN_MP_INIT_MULTI_C
@@ -273,6 +275,13 @@
#if defined(BN_MP_COUNT_BITS_C)
#endif
+#if defined(BN_MP_DECR_C)
+# define BN_MP_SET_C
+# define BN_MP_INCR_C
+# define BN_MP_ZERO_C
+# define BN_MP_SUB_D_C
+#endif
+
#if defined(BN_MP_DIV_C)
# define BN_MP_CMP_MAG_C
# define BN_MP_COPY_C
@@ -460,6 +469,12 @@
# define BN_MP_CLAMP_C
#endif
+#if defined(BN_MP_INCR_C)
+# define BN_MP_SET_C
+# define BN_MP_DECR_C
+# define BN_MP_ADD_D_C
+#endif
+
#if defined(BN_MP_INIT_C)
#endif