-
+ 1D6A019FD026BF2712BE8E24EB9BAC995524336DF8EA4BF08878BDA3F95A943139E68381347974FEEA6DDAF3748ECD837FD698875324CB16C2AF13AF1E54BAA0
eucrypt/mpi/mpi-add.c
(0 . 0)(1 . 240)
2703 /* mpi-add.c - MPI functions
2704 * Modified by No Such Labs. (C) 2015. See README.
2705 *
2706 * This file was originally part of Gnu Privacy Guard (GPG), ver. 1.4.10,
2707 * SHA256(gnupg-1.4.10.tar.gz):
2708 * 0bfd74660a2f6cedcf7d8256db4a63c996ffebbcdc2cf54397bfb72878c5a85a
2709 * (C) 1994-2005 Free Software Foundation, Inc.
2710 *
2711 * This program is free software: you can redistribute it and/or modify
2712 * it under the terms of the GNU General Public License as published by
2713 * the Free Software Foundation, either version 3 of the License, or
2714 * (at your option) any later version.
2715 *
2716 * This program is distributed in the hope that it will be useful,
2717 * but WITHOUT ANY WARRANTY; without even the implied warranty of
2718 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2719 * GNU General Public License for more details.
2720 *
2721 * You should have received a copy of the GNU General Public License
2722 * along with this program. If not, see <http://www.gnu.org/licenses/>.
2723 */
2724
2725 #include <stdio.h>
2726 #include <stdlib.h>
2727
2728 #include "knobs.h"
2729 #include "mpi-internal.h"
2730
2731
2732 /****************
2733 * Add the unsigned integer V to the mpi-integer U and store the
2734 * result in W. U and V may be the same.
2735 */
2736 void
2737 mpi_add_ui(MPI w, MPI u, unsigned long v )
2738 {
2739 mpi_ptr_t wp, up;
2740 mpi_size_t usize, wsize;
2741 int usign, wsign;
2742
2743 usize = u->nlimbs;
2744 usign = u->sign;
2745 wsign = 0;
2746
2747 /* If not space for W (and possible carry), increase space. */
2748 wsize = usize + 1;
2749 if( w->alloced < wsize )
2750 mpi_resize(w, wsize);
2751
2752 /* These must be after realloc (U may be the same as W). */
2753 up = u->d;
2754 wp = w->d;
2755
2756 if( !usize ) { /* simple */
2757 wp[0] = v;
2758 wsize = v? 1:0;
2759 }
2760 else if( !usign ) { /* mpi is not negative */
2761 mpi_limb_t cy;
2762 cy = mpihelp_add_1(wp, up, usize, v);
2763 wp[usize] = cy;
2764 wsize = usize + cy;
2765 }
2766 else { /* The signs are different. Need exact comparison to determine
2767 * which operand to subtract from which. */
2768 if( usize == 1 && up[0] < v ) {
2769 wp[0] = v - up[0];
2770 wsize = 1;
2771 }
2772 else {
2773 mpihelp_sub_1(wp, up, usize, v);
2774 /* Size can decrease with at most one limb. */
2775 wsize = usize - (wp[usize-1]==0);
2776 wsign = 1;
2777 }
2778 }
2779
2780 w->nlimbs = wsize;
2781 w->sign = wsign;
2782 }
2783
2784
2785 void
2786 mpi_add(MPI w, MPI u, MPI v)
2787 {
2788 mpi_ptr_t wp, up, vp;
2789 mpi_size_t usize, vsize, wsize;
2790 int usign, vsign, wsign;
2791
2792 if( u->nlimbs < v->nlimbs ) { /* Swap U and V. */
2793 usize = v->nlimbs;
2794 usign = v->sign;
2795 vsize = u->nlimbs;
2796 vsign = u->sign;
2797 wsize = usize + 1;
2798 RESIZE_IF_NEEDED(w, wsize);
2799 /* These must be after realloc (u or v may be the same as w). */
2800 up = v->d;
2801 vp = u->d;
2802 }
2803 else {
2804 usize = u->nlimbs;
2805 usign = u->sign;
2806 vsize = v->nlimbs;
2807 vsign = v->sign;
2808 wsize = usize + 1;
2809 RESIZE_IF_NEEDED(w, wsize);
2810 /* These must be after realloc (u or v may be the same as w). */
2811 up = u->d;
2812 vp = v->d;
2813 }
2814 wp = w->d;
2815 wsign = 0;
2816
2817 if( !vsize ) { /* simple */
2818 MPN_COPY(wp, up, usize );
2819 wsize = usize;
2820 wsign = usign;
2821 }
2822 else if( usign != vsign ) { /* different sign */
2823 /* This test is right since USIZE >= VSIZE */
2824 if( usize != vsize ) {
2825 mpihelp_sub(wp, up, usize, vp, vsize);
2826 wsize = usize;
2827 MPN_NORMALIZE(wp, wsize);
2828 wsign = usign;
2829 }
2830 else if( mpihelp_cmp(up, vp, usize) < 0 ) {
2831 mpihelp_sub_n(wp, vp, up, usize);
2832 wsize = usize;
2833 MPN_NORMALIZE(wp, wsize);
2834 if( !usign )
2835 wsign = 1;
2836 }
2837 else {
2838 mpihelp_sub_n(wp, up, vp, usize);
2839 wsize = usize;
2840 MPN_NORMALIZE(wp, wsize);
2841 if( usign )
2842 wsign = 1;
2843 }
2844 }
2845 else { /* U and V have same sign. Add them. */
2846 mpi_limb_t cy = mpihelp_add(wp, up, usize, vp, vsize);
2847 wp[usize] = cy;
2848 wsize = usize + cy;
2849 if( usign )
2850 wsign = 1;
2851 }
2852
2853 w->nlimbs = wsize;
2854 w->sign = wsign;
2855 }
2856
2857
2858 /****************
2859 * Subtract the unsigned integer V from the mpi-integer U and store the
2860 * result in W.
2861 */
2862 void
2863 mpi_sub_ui(MPI w, MPI u, unsigned long v )
2864 {
2865 mpi_ptr_t wp, up;
2866 mpi_size_t usize, wsize;
2867 int usign, wsign;
2868
2869 usize = u->nlimbs;
2870 usign = u->sign;
2871 wsign = 0;
2872
2873 /* If not space for W (and possible carry), increase space. */
2874 wsize = usize + 1;
2875 if( w->alloced < wsize )
2876 mpi_resize(w, wsize);
2877
2878 /* These must be after realloc (U may be the same as W). */
2879 up = u->d;
2880 wp = w->d;
2881
2882 if( !usize ) { /* simple */
2883 wp[0] = v;
2884 wsize = v? 1:0;
2885 wsign = 1;
2886 }
2887 else if( usign ) { /* mpi and v are negative */
2888 mpi_limb_t cy;
2889 cy = mpihelp_add_1(wp, up, usize, v);
2890 wp[usize] = cy;
2891 wsize = usize + cy;
2892 }
2893 else { /* The signs are different. Need exact comparison to determine
2894 * which operand to subtract from which. */
2895 if( usize == 1 && up[0] < v ) {
2896 wp[0] = v - up[0];
2897 wsize = 1;
2898 wsign = 1;
2899 }
2900 else {
2901 mpihelp_sub_1(wp, up, usize, v);
2902 /* Size can decrease with at most one limb. */
2903 wsize = usize - (wp[usize-1]==0);
2904 }
2905 }
2906
2907 w->nlimbs = wsize;
2908 w->sign = wsign;
2909 }
2910
2911 void
2912 mpi_sub(MPI w, MPI u, MPI v)
2913 {
2914 if( w == v ) {
2915 MPI vv = mpi_copy(v);
2916 vv->sign = !vv->sign;
2917 mpi_add( w, u, vv );
2918 mpi_free(vv);
2919 }
2920 else {
2921 /* fixme: this is not thread-save (we temp. modify v) */
2922 v->sign = !v->sign;
2923 mpi_add( w, u, v );
2924 v->sign = !v->sign;
2925 }
2926 }
2927
2928
2929 void
2930 mpi_addm( MPI w, MPI u, MPI v, MPI m)
2931 {
2932 mpi_add(w, u, v);
2933 mpi_fdiv_r( w, w, m );
2934 }
2935
2936 void
2937 mpi_subm( MPI w, MPI u, MPI v, MPI m)
2938 {
2939 mpi_sub(w, u, v);
2940 mpi_fdiv_r( w, w, m );
2941 }
2942