diff options
Diffstat (limited to 'src/data.c')
| -rw-r--r-- | src/data.c | 669 |
1 files changed, 265 insertions, 404 deletions
diff --git a/src/data.c b/src/data.c index 6afda1e6fb9..7be2052362b 100644 --- a/src/data.c +++ b/src/data.c | |||
| @@ -2832,232 +2832,186 @@ enum arithop | |||
| 2832 | Alogior, | 2832 | Alogior, |
| 2833 | Alogxor | 2833 | Alogxor |
| 2834 | }; | 2834 | }; |
| 2835 | 2835 | static bool | |
| 2836 | enum { FIXNUMS_FIT_IN_LONG = (LONG_MIN <= MOST_NEGATIVE_FIXNUM | 2836 | floating_point_op (enum arithop code) |
| 2837 | && MOST_POSITIVE_FIXNUM <= LONG_MAX) }; | ||
| 2838 | |||
| 2839 | static void | ||
| 2840 | free_mpz_value (void *value_ptr) | ||
| 2841 | { | 2837 | { |
| 2842 | mpz_clear (*(mpz_t *) value_ptr); | 2838 | return code <= Adiv; |
| 2843 | } | 2839 | } |
| 2844 | 2840 | ||
| 2845 | static Lisp_Object float_arith_driver (double, ptrdiff_t, enum arithop, | 2841 | /* Return the result of applying the floating-point operation CODE to |
| 2846 | ptrdiff_t, Lisp_Object *); | 2842 | the NARGS arguments starting at ARGS. If ARGNUM is positive, |
| 2843 | ARGNUM of the arguments were already consumed, yielding ACCUM. | ||
| 2844 | 0 <= ARGNUM < NARGS, 2 <= NARGS, and NEXT is the value of | ||
| 2845 | ARGS[ARGSNUM], converted to double. */ | ||
| 2847 | 2846 | ||
| 2848 | static Lisp_Object | 2847 | static Lisp_Object |
| 2849 | arith_driver (enum arithop code, ptrdiff_t nargs, Lisp_Object *args) | 2848 | floatop_arith_driver (enum arithop code, ptrdiff_t nargs, Lisp_Object *args, |
| 2849 | ptrdiff_t argnum, double accum, double next) | ||
| 2850 | { | 2850 | { |
| 2851 | Lisp_Object val = Qnil; | 2851 | if (argnum == 0) |
| 2852 | ptrdiff_t argnum; | ||
| 2853 | ptrdiff_t count = SPECPDL_INDEX (); | ||
| 2854 | mpz_t accum; | ||
| 2855 | |||
| 2856 | mpz_init (accum); | ||
| 2857 | record_unwind_protect_ptr (free_mpz_value, &accum); | ||
| 2858 | |||
| 2859 | switch (code) | ||
| 2860 | { | 2852 | { |
| 2861 | case Alogior: | 2853 | accum = next; |
| 2862 | case Alogxor: | 2854 | goto next_arg; |
| 2863 | case Aadd: | ||
| 2864 | case Asub: | ||
| 2865 | /* ACCUM is already 0. */ | ||
| 2866 | break; | ||
| 2867 | case Amult: | ||
| 2868 | case Adiv: | ||
| 2869 | mpz_set_si (accum, 1); | ||
| 2870 | break; | ||
| 2871 | case Alogand: | ||
| 2872 | mpz_set_si (accum, -1); | ||
| 2873 | break; | ||
| 2874 | default: | ||
| 2875 | break; | ||
| 2876 | } | 2855 | } |
| 2877 | 2856 | ||
| 2878 | for (argnum = 0; argnum < nargs; argnum++) | 2857 | while (true) |
| 2879 | { | 2858 | { |
| 2880 | /* Using args[argnum] as argument to CHECK_NUMBER... */ | ||
| 2881 | val = args[argnum]; | ||
| 2882 | CHECK_NUMBER_COERCE_MARKER (val); | ||
| 2883 | |||
| 2884 | if (FLOATP (val)) | ||
| 2885 | return unbind_to (count, | ||
| 2886 | float_arith_driver (mpz_get_d (accum), argnum, code, | ||
| 2887 | nargs, args)); | ||
| 2888 | switch (code) | 2859 | switch (code) |
| 2889 | { | 2860 | { |
| 2890 | case Aadd: | 2861 | case Aadd : accum += next; break; |
| 2891 | if (BIGNUMP (val)) | 2862 | case Asub : accum -= next; break; |
| 2892 | mpz_add (accum, accum, XBIGNUM (val)->value); | 2863 | case Amult: accum *= next; break; |
| 2893 | else if (! FIXNUMS_FIT_IN_LONG) | ||
| 2894 | { | ||
| 2895 | mpz_t tem; | ||
| 2896 | mpz_init (tem); | ||
| 2897 | mpz_set_intmax (tem, XFIXNUM (val)); | ||
| 2898 | mpz_add (accum, accum, tem); | ||
| 2899 | mpz_clear (tem); | ||
| 2900 | } | ||
| 2901 | else if (XFIXNUM (val) < 0) | ||
| 2902 | mpz_sub_ui (accum, accum, - XFIXNUM (val)); | ||
| 2903 | else | ||
| 2904 | mpz_add_ui (accum, accum, XFIXNUM (val)); | ||
| 2905 | break; | ||
| 2906 | case Asub: | ||
| 2907 | if (! argnum) | ||
| 2908 | { | ||
| 2909 | if (BIGNUMP (val)) | ||
| 2910 | mpz_set (accum, XBIGNUM (val)->value); | ||
| 2911 | else | ||
| 2912 | mpz_set_intmax (accum, XFIXNUM (val)); | ||
| 2913 | if (nargs == 1) | ||
| 2914 | mpz_neg (accum, accum); | ||
| 2915 | } | ||
| 2916 | else if (BIGNUMP (val)) | ||
| 2917 | mpz_sub (accum, accum, XBIGNUM (val)->value); | ||
| 2918 | else if (! FIXNUMS_FIT_IN_LONG) | ||
| 2919 | { | ||
| 2920 | mpz_t tem; | ||
| 2921 | mpz_init (tem); | ||
| 2922 | mpz_set_intmax (tem, XFIXNUM (val)); | ||
| 2923 | mpz_sub (accum, accum, tem); | ||
| 2924 | mpz_clear (tem); | ||
| 2925 | } | ||
| 2926 | else if (XFIXNUM (val) < 0) | ||
| 2927 | mpz_add_ui (accum, accum, - XFIXNUM (val)); | ||
| 2928 | else | ||
| 2929 | mpz_sub_ui (accum, accum, XFIXNUM (val)); | ||
| 2930 | break; | ||
| 2931 | case Amult: | ||
| 2932 | if (BIGNUMP (val)) | ||
| 2933 | emacs_mpz_mul (accum, accum, XBIGNUM (val)->value); | ||
| 2934 | else if (! FIXNUMS_FIT_IN_LONG) | ||
| 2935 | { | ||
| 2936 | mpz_t tem; | ||
| 2937 | mpz_init (tem); | ||
| 2938 | mpz_set_intmax (tem, XFIXNUM (val)); | ||
| 2939 | emacs_mpz_mul (accum, accum, tem); | ||
| 2940 | mpz_clear (tem); | ||
| 2941 | } | ||
| 2942 | else | ||
| 2943 | mpz_mul_si (accum, accum, XFIXNUM (val)); | ||
| 2944 | break; | ||
| 2945 | case Adiv: | 2864 | case Adiv: |
| 2946 | if (! (argnum || nargs == 1)) | 2865 | if (! IEEE_FLOATING_POINT && next == 0) |
| 2947 | { | 2866 | xsignal0 (Qarith_error); |
| 2948 | if (BIGNUMP (val)) | 2867 | accum /= next; |
| 2949 | mpz_set (accum, XBIGNUM (val)->value); | ||
| 2950 | else | ||
| 2951 | mpz_set_intmax (accum, XFIXNUM (val)); | ||
| 2952 | } | ||
| 2953 | else | ||
| 2954 | { | ||
| 2955 | /* Note that a bignum can never be 0, so we don't need | ||
| 2956 | to check that case. */ | ||
| 2957 | if (BIGNUMP (val)) | ||
| 2958 | mpz_tdiv_q (accum, accum, XBIGNUM (val)->value); | ||
| 2959 | else if (XFIXNUM (val) == 0) | ||
| 2960 | xsignal0 (Qarith_error); | ||
| 2961 | else if (ULONG_MAX < -MOST_NEGATIVE_FIXNUM) | ||
| 2962 | { | ||
| 2963 | mpz_t tem; | ||
| 2964 | mpz_init (tem); | ||
| 2965 | mpz_set_intmax (tem, XFIXNUM (val)); | ||
| 2966 | mpz_tdiv_q (accum, accum, tem); | ||
| 2967 | mpz_clear (tem); | ||
| 2968 | } | ||
| 2969 | else | ||
| 2970 | { | ||
| 2971 | EMACS_INT value = XFIXNUM (val); | ||
| 2972 | mpz_tdiv_q_ui (accum, accum, eabs (value)); | ||
| 2973 | if (value < 0) | ||
| 2974 | mpz_neg (accum, accum); | ||
| 2975 | } | ||
| 2976 | } | ||
| 2977 | break; | ||
| 2978 | case Alogand: | ||
| 2979 | if (BIGNUMP (val)) | ||
| 2980 | mpz_and (accum, accum, XBIGNUM (val)->value); | ||
| 2981 | else | ||
| 2982 | { | ||
| 2983 | mpz_t tem; | ||
| 2984 | mpz_init (tem); | ||
| 2985 | mpz_set_intmax (tem, XFIXNUM (val)); | ||
| 2986 | mpz_and (accum, accum, tem); | ||
| 2987 | mpz_clear (tem); | ||
| 2988 | } | ||
| 2989 | break; | ||
| 2990 | case Alogior: | ||
| 2991 | if (BIGNUMP (val)) | ||
| 2992 | mpz_ior (accum, accum, XBIGNUM (val)->value); | ||
| 2993 | else | ||
| 2994 | { | ||
| 2995 | mpz_t tem; | ||
| 2996 | mpz_init (tem); | ||
| 2997 | mpz_set_intmax (tem, XFIXNUM (val)); | ||
| 2998 | mpz_ior (accum, accum, tem); | ||
| 2999 | mpz_clear (tem); | ||
| 3000 | } | ||
| 3001 | break; | ||
| 3002 | case Alogxor: | ||
| 3003 | if (BIGNUMP (val)) | ||
| 3004 | mpz_xor (accum, accum, XBIGNUM (val)->value); | ||
| 3005 | else | ||
| 3006 | { | ||
| 3007 | mpz_t tem; | ||
| 3008 | mpz_init (tem); | ||
| 3009 | mpz_set_intmax (tem, XFIXNUM (val)); | ||
| 3010 | mpz_xor (accum, accum, tem); | ||
| 3011 | mpz_clear (tem); | ||
| 3012 | } | ||
| 3013 | break; | 2868 | break; |
| 2869 | default: eassume (false); | ||
| 3014 | } | 2870 | } |
| 2871 | |||
| 2872 | next_arg: | ||
| 2873 | argnum++; | ||
| 2874 | if (argnum == nargs) | ||
| 2875 | return make_float (accum); | ||
| 2876 | Lisp_Object val = args[argnum]; | ||
| 2877 | CHECK_NUMBER_COERCE_MARKER (val); | ||
| 2878 | next = XFLOATINT (val); | ||
| 3015 | } | 2879 | } |
| 2880 | } | ||
| 2881 | |||
| 2882 | /* Like floatop_arith_driver, except CODE might not be a floating-point | ||
| 2883 | operation, and NEXT is a Lisp float rather than a C double. */ | ||
| 3016 | 2884 | ||
| 3017 | return unbind_to (count, make_integer (accum)); | 2885 | static Lisp_Object |
| 2886 | float_arith_driver (enum arithop code, ptrdiff_t nargs, Lisp_Object *args, | ||
| 2887 | ptrdiff_t argnum, double accum, Lisp_Object next) | ||
| 2888 | { | ||
| 2889 | if (! floating_point_op (code)) | ||
| 2890 | wrong_type_argument (Qinteger_or_marker_p, next); | ||
| 2891 | return floatop_arith_driver (code, nargs, args, argnum, accum, | ||
| 2892 | XFLOAT_DATA (next)); | ||
| 3018 | } | 2893 | } |
| 3019 | 2894 | ||
| 2895 | /* Return the result of applying the arithmetic operation CODE to the | ||
| 2896 | NARGS arguments starting at ARGS. If ARGNUM is positive, ARGNUM of | ||
| 2897 | the arguments were already consumed, yielding IACCUM. 0 <= ARGNUM | ||
| 2898 | < NARGS, 2 <= NARGS, and VAL is the value of ARGS[ARGSNUM], | ||
| 2899 | converted to integer. */ | ||
| 2900 | |||
| 3020 | static Lisp_Object | 2901 | static Lisp_Object |
| 3021 | float_arith_driver (double accum, ptrdiff_t argnum, enum arithop code, | 2902 | bignum_arith_driver (enum arithop code, ptrdiff_t nargs, Lisp_Object *args, |
| 3022 | ptrdiff_t nargs, Lisp_Object *args) | 2903 | ptrdiff_t argnum, intmax_t iaccum, Lisp_Object val) |
| 3023 | { | 2904 | { |
| 3024 | for (; argnum < nargs; argnum++) | 2905 | mpz_t *accum; |
| 2906 | if (argnum == 0) | ||
| 3025 | { | 2907 | { |
| 3026 | Lisp_Object val = args[argnum]; | 2908 | accum = bignum_integer (&mpz[0], val); |
| 3027 | CHECK_NUMBER_COERCE_MARKER (val); | 2909 | goto next_arg; |
| 3028 | double next = (FIXNUMP (val) ? XFIXNUM (val) | 2910 | } |
| 3029 | : FLOATP (val) ? XFLOAT_DATA (val) | 2911 | mpz_set_intmax (mpz[0], iaccum); |
| 3030 | : mpz_get_d (XBIGNUM (val)->value)); | 2912 | accum = &mpz[0]; |
| 2913 | |||
| 2914 | while (true) | ||
| 2915 | { | ||
| 2916 | mpz_t *next = bignum_integer (&mpz[1], val); | ||
| 3031 | 2917 | ||
| 3032 | switch (code) | 2918 | switch (code) |
| 3033 | { | 2919 | { |
| 3034 | case Aadd: | 2920 | case Aadd : mpz_add (mpz[0], *accum, *next); break; |
| 3035 | accum += next; | 2921 | case Asub : mpz_sub (mpz[0], *accum, *next); break; |
| 3036 | break; | 2922 | case Amult : emacs_mpz_mul (mpz[0], *accum, *next); break; |
| 3037 | case Asub: | 2923 | case Alogand: mpz_and (mpz[0], *accum, *next); break; |
| 3038 | accum = argnum ? accum - next : nargs == 1 ? - next : next; | 2924 | case Alogior: mpz_ior (mpz[0], *accum, *next); break; |
| 3039 | break; | 2925 | case Alogxor: mpz_xor (mpz[0], *accum, *next); break; |
| 3040 | case Amult: | ||
| 3041 | accum *= next; | ||
| 3042 | break; | ||
| 3043 | case Adiv: | 2926 | case Adiv: |
| 3044 | if (! (argnum || nargs == 1)) | 2927 | if (mpz_sgn (*next) == 0) |
| 3045 | accum = next; | 2928 | xsignal0 (Qarith_error); |
| 3046 | else | 2929 | mpz_tdiv_q (mpz[0], *accum, *next); |
| 3047 | { | ||
| 3048 | if (! IEEE_FLOATING_POINT && next == 0) | ||
| 3049 | xsignal0 (Qarith_error); | ||
| 3050 | accum /= next; | ||
| 3051 | } | ||
| 3052 | break; | 2930 | break; |
| 3053 | case Alogand: | 2931 | default: |
| 3054 | case Alogior: | 2932 | eassume (false); |
| 3055 | case Alogxor: | ||
| 3056 | wrong_type_argument (Qinteger_or_marker_p, val); | ||
| 3057 | } | 2933 | } |
| 2934 | accum = &mpz[0]; | ||
| 2935 | |||
| 2936 | next_arg: | ||
| 2937 | argnum++; | ||
| 2938 | if (argnum == nargs) | ||
| 2939 | return make_integer_mpz (); | ||
| 2940 | val = args[argnum]; | ||
| 2941 | CHECK_NUMBER_COERCE_MARKER (val); | ||
| 2942 | if (FLOATP (val)) | ||
| 2943 | float_arith_driver (code, nargs, args, argnum, | ||
| 2944 | mpz_get_d (*accum), val); | ||
| 3058 | } | 2945 | } |
| 2946 | } | ||
| 2947 | |||
| 2948 | /* Return the result of applying the arithmetic operation CODE to the | ||
| 2949 | NARGS arguments starting at ARGS, with the first argument being the | ||
| 2950 | number VAL. 2 <= NARGS. Check that the remaining arguments are | ||
| 2951 | numbers or markers. */ | ||
| 2952 | |||
| 2953 | static Lisp_Object | ||
| 2954 | arith_driver (enum arithop code, ptrdiff_t nargs, Lisp_Object *args, | ||
| 2955 | Lisp_Object val) | ||
| 2956 | { | ||
| 2957 | eassume (2 <= nargs); | ||
| 2958 | |||
| 2959 | ptrdiff_t argnum = 0; | ||
| 2960 | /* Set ACCUM to VAL's value if it is a fixnum, otherwise to some | ||
| 2961 | ignored value to avoid using an uninitialized variable later. */ | ||
| 2962 | intmax_t accum = XFIXNUM (val); | ||
| 2963 | |||
| 2964 | if (FIXNUMP (val)) | ||
| 2965 | while (true) | ||
| 2966 | { | ||
| 2967 | argnum++; | ||
| 2968 | if (argnum == nargs) | ||
| 2969 | return make_int (accum); | ||
| 2970 | val = args[argnum]; | ||
| 2971 | CHECK_NUMBER_COERCE_MARKER (val); | ||
| 2972 | |||
| 2973 | /* Set NEXT to the next value if it fits, else exit the loop. */ | ||
| 2974 | intmax_t next; | ||
| 2975 | if (FIXNUMP (val)) | ||
| 2976 | next = XFIXNUM (val); | ||
| 2977 | else if (FLOATP (val)) | ||
| 2978 | break; | ||
| 2979 | else | ||
| 2980 | { | ||
| 2981 | next = bignum_to_intmax (val); | ||
| 2982 | if (next == 0) | ||
| 2983 | break; | ||
| 2984 | } | ||
| 2985 | |||
| 2986 | /* Set ACCUM to the next operation's result if it fits, | ||
| 2987 | else exit the loop. */ | ||
| 2988 | bool overflow = false; | ||
| 2989 | intmax_t a; | ||
| 2990 | switch (code) | ||
| 2991 | { | ||
| 2992 | case Aadd : overflow = INT_ADD_WRAPV (accum, next, &a); break; | ||
| 2993 | case Amult: overflow = INT_MULTIPLY_WRAPV (accum, next, &a); break; | ||
| 2994 | case Asub : overflow = INT_SUBTRACT_WRAPV (accum, next, &a); break; | ||
| 2995 | case Adiv: | ||
| 2996 | if (next == 0) | ||
| 2997 | xsignal0 (Qarith_error); | ||
| 2998 | overflow = INT_DIVIDE_OVERFLOW (accum, next); | ||
| 2999 | if (!overflow) | ||
| 3000 | a = accum / next; | ||
| 3001 | break; | ||
| 3002 | case Alogand: accum &= next; continue; | ||
| 3003 | case Alogior: accum |= next; continue; | ||
| 3004 | case Alogxor: accum ^= next; continue; | ||
| 3005 | default: eassume (false); | ||
| 3006 | } | ||
| 3007 | if (overflow) | ||
| 3008 | break; | ||
| 3009 | accum = a; | ||
| 3010 | } | ||
| 3059 | 3011 | ||
| 3060 | return make_float (accum); | 3012 | return (FLOATP (val) |
| 3013 | ? float_arith_driver (code, nargs, args, argnum, accum, val) | ||
| 3014 | : bignum_arith_driver (code, nargs, args, argnum, accum, val)); | ||
| 3061 | } | 3015 | } |
| 3062 | 3016 | ||
| 3063 | 3017 | ||
| @@ -3066,7 +3020,11 @@ DEFUN ("+", Fplus, Splus, 0, MANY, 0, | |||
| 3066 | usage: (+ &rest NUMBERS-OR-MARKERS) */) | 3020 | usage: (+ &rest NUMBERS-OR-MARKERS) */) |
| 3067 | (ptrdiff_t nargs, Lisp_Object *args) | 3021 | (ptrdiff_t nargs, Lisp_Object *args) |
| 3068 | { | 3022 | { |
| 3069 | return arith_driver (Aadd, nargs, args); | 3023 | if (nargs == 0) |
| 3024 | return make_fixnum (0); | ||
| 3025 | Lisp_Object a = args[0]; | ||
| 3026 | CHECK_NUMBER_COERCE_MARKER (a); | ||
| 3027 | return nargs == 1 ? a : arith_driver (Aadd, nargs, args, a); | ||
| 3070 | } | 3028 | } |
| 3071 | 3029 | ||
| 3072 | DEFUN ("-", Fminus, Sminus, 0, MANY, 0, | 3030 | DEFUN ("-", Fminus, Sminus, 0, MANY, 0, |
| @@ -3076,7 +3034,20 @@ subtracts all but the first from the first. | |||
| 3076 | usage: (- &optional NUMBER-OR-MARKER &rest MORE-NUMBERS-OR-MARKERS) */) | 3034 | usage: (- &optional NUMBER-OR-MARKER &rest MORE-NUMBERS-OR-MARKERS) */) |
| 3077 | (ptrdiff_t nargs, Lisp_Object *args) | 3035 | (ptrdiff_t nargs, Lisp_Object *args) |
| 3078 | { | 3036 | { |
| 3079 | return arith_driver (Asub, nargs, args); | 3037 | if (nargs == 0) |
| 3038 | return make_fixnum (0); | ||
| 3039 | Lisp_Object a = args[0]; | ||
| 3040 | CHECK_NUMBER_COERCE_MARKER (a); | ||
| 3041 | if (nargs == 1) | ||
| 3042 | { | ||
| 3043 | if (FIXNUMP (a)) | ||
| 3044 | return make_int (-XFIXNUM (a)); | ||
| 3045 | if (FLOATP (a)) | ||
| 3046 | return make_float (-XFLOAT_DATA (a)); | ||
| 3047 | mpz_neg (mpz[0], XBIGNUM (a)->value); | ||
| 3048 | return make_integer_mpz (); | ||
| 3049 | } | ||
| 3050 | return arith_driver (Asub, nargs, args, a); | ||
| 3080 | } | 3051 | } |
| 3081 | 3052 | ||
| 3082 | DEFUN ("*", Ftimes, Stimes, 0, MANY, 0, | 3053 | DEFUN ("*", Ftimes, Stimes, 0, MANY, 0, |
| @@ -3084,7 +3055,11 @@ DEFUN ("*", Ftimes, Stimes, 0, MANY, 0, | |||
| 3084 | usage: (* &rest NUMBERS-OR-MARKERS) */) | 3055 | usage: (* &rest NUMBERS-OR-MARKERS) */) |
| 3085 | (ptrdiff_t nargs, Lisp_Object *args) | 3056 | (ptrdiff_t nargs, Lisp_Object *args) |
| 3086 | { | 3057 | { |
| 3087 | return arith_driver (Amult, nargs, args); | 3058 | if (nargs == 0) |
| 3059 | return make_fixnum (1); | ||
| 3060 | Lisp_Object a = args[0]; | ||
| 3061 | CHECK_NUMBER_COERCE_MARKER (a); | ||
| 3062 | return nargs == 1 ? a : arith_driver (Amult, nargs, args, a); | ||
| 3088 | } | 3063 | } |
| 3089 | 3064 | ||
| 3090 | DEFUN ("/", Fquo, Squo, 1, MANY, 0, | 3065 | DEFUN ("/", Fquo, Squo, 1, MANY, 0, |
| @@ -3095,11 +3070,31 @@ The arguments must be numbers or markers. | |||
| 3095 | usage: (/ NUMBER &rest DIVISORS) */) | 3070 | usage: (/ NUMBER &rest DIVISORS) */) |
| 3096 | (ptrdiff_t nargs, Lisp_Object *args) | 3071 | (ptrdiff_t nargs, Lisp_Object *args) |
| 3097 | { | 3072 | { |
| 3098 | ptrdiff_t argnum; | 3073 | Lisp_Object a = args[0]; |
| 3099 | for (argnum = 2; argnum < nargs; argnum++) | 3074 | CHECK_NUMBER_COERCE_MARKER (a); |
| 3075 | if (nargs == 1) | ||
| 3076 | { | ||
| 3077 | if (FIXNUMP (a)) | ||
| 3078 | { | ||
| 3079 | if (XFIXNUM (a) == 0) | ||
| 3080 | xsignal0 (Qarith_error); | ||
| 3081 | return make_fixnum (1 / XFIXNUM (a)); | ||
| 3082 | } | ||
| 3083 | if (FLOATP (a)) | ||
| 3084 | { | ||
| 3085 | if (! IEEE_FLOATING_POINT && XFLOAT_DATA (a) == 0) | ||
| 3086 | xsignal0 (Qarith_error); | ||
| 3087 | return make_float (1 / XFLOAT_DATA (a)); | ||
| 3088 | } | ||
| 3089 | /* Dividing 1 by any bignum yields 0. */ | ||
| 3090 | return make_fixnum (0); | ||
| 3091 | } | ||
| 3092 | |||
| 3093 | /* Do all computation in floating-point if any arg is a float. */ | ||
| 3094 | for (ptrdiff_t argnum = 2; argnum < nargs; argnum++) | ||
| 3100 | if (FLOATP (args[argnum])) | 3095 | if (FLOATP (args[argnum])) |
| 3101 | return float_arith_driver (0, 0, Adiv, nargs, args); | 3096 | return floatop_arith_driver (Adiv, nargs, args, 0, 0, XFLOATINT (a)); |
| 3102 | return arith_driver (Adiv, nargs, args); | 3097 | return arith_driver (Adiv, nargs, args, a); |
| 3103 | } | 3098 | } |
| 3104 | 3099 | ||
| 3105 | DEFUN ("%", Frem, Srem, 2, 2, 0, | 3100 | DEFUN ("%", Frem, Srem, 2, 2, 0, |
| @@ -3107,52 +3102,22 @@ DEFUN ("%", Frem, Srem, 2, 2, 0, | |||
| 3107 | Both must be integers or markers. */) | 3102 | Both must be integers or markers. */) |
| 3108 | (register Lisp_Object x, Lisp_Object y) | 3103 | (register Lisp_Object x, Lisp_Object y) |
| 3109 | { | 3104 | { |
| 3110 | Lisp_Object val; | ||
| 3111 | |||
| 3112 | CHECK_INTEGER_COERCE_MARKER (x); | 3105 | CHECK_INTEGER_COERCE_MARKER (x); |
| 3113 | CHECK_INTEGER_COERCE_MARKER (y); | 3106 | CHECK_INTEGER_COERCE_MARKER (y); |
| 3114 | 3107 | ||
| 3115 | /* Note that a bignum can never be 0, so we don't need to check that | 3108 | /* A bignum can never be 0, so don't check that case. */ |
| 3116 | case. */ | ||
| 3117 | if (FIXNUMP (y) && XFIXNUM (y) == 0) | 3109 | if (FIXNUMP (y) && XFIXNUM (y) == 0) |
| 3118 | xsignal0 (Qarith_error); | 3110 | xsignal0 (Qarith_error); |
| 3119 | 3111 | ||
| 3120 | if (FIXNUMP (x) && FIXNUMP (y)) | 3112 | if (FIXNUMP (x) && FIXNUMP (y)) |
| 3121 | XSETINT (val, XFIXNUM (x) % XFIXNUM (y)); | 3113 | return make_fixnum (XFIXNUM (x) % XFIXNUM (y)); |
| 3122 | else | 3114 | else |
| 3123 | { | 3115 | { |
| 3124 | mpz_t xm, ym, *xmp, *ymp; | 3116 | mpz_tdiv_r (mpz[0], |
| 3125 | mpz_t result; | 3117 | *bignum_integer (&mpz[0], x), |
| 3126 | 3118 | *bignum_integer (&mpz[1], y)); | |
| 3127 | if (BIGNUMP (x)) | 3119 | return make_integer_mpz (); |
| 3128 | xmp = &XBIGNUM (x)->value; | ||
| 3129 | else | ||
| 3130 | { | ||
| 3131 | mpz_init (xm); | ||
| 3132 | mpz_set_intmax (xm, XFIXNUM (x)); | ||
| 3133 | xmp = &xm; | ||
| 3134 | } | ||
| 3135 | |||
| 3136 | if (BIGNUMP (y)) | ||
| 3137 | ymp = &XBIGNUM (y)->value; | ||
| 3138 | else | ||
| 3139 | { | ||
| 3140 | mpz_init (ym); | ||
| 3141 | mpz_set_intmax (ym, XFIXNUM (y)); | ||
| 3142 | ymp = &ym; | ||
| 3143 | } | ||
| 3144 | |||
| 3145 | mpz_init (result); | ||
| 3146 | mpz_tdiv_r (result, *xmp, *ymp); | ||
| 3147 | val = make_integer (result); | ||
| 3148 | mpz_clear (result); | ||
| 3149 | |||
| 3150 | if (xmp == &xm) | ||
| 3151 | mpz_clear (xm); | ||
| 3152 | if (ymp == &ym) | ||
| 3153 | mpz_clear (ym); | ||
| 3154 | } | 3120 | } |
| 3155 | return val; | ||
| 3156 | } | 3121 | } |
| 3157 | 3122 | ||
| 3158 | DEFUN ("mod", Fmod, Smod, 2, 2, 0, | 3123 | DEFUN ("mod", Fmod, Smod, 2, 2, 0, |
| @@ -3161,9 +3126,6 @@ The result falls between zero (inclusive) and Y (exclusive). | |||
| 3161 | Both X and Y must be numbers or markers. */) | 3126 | Both X and Y must be numbers or markers. */) |
| 3162 | (register Lisp_Object x, Lisp_Object y) | 3127 | (register Lisp_Object x, Lisp_Object y) |
| 3163 | { | 3128 | { |
| 3164 | Lisp_Object val; | ||
| 3165 | EMACS_INT i1, i2; | ||
| 3166 | |||
| 3167 | CHECK_NUMBER_COERCE_MARKER (x); | 3129 | CHECK_NUMBER_COERCE_MARKER (x); |
| 3168 | CHECK_NUMBER_COERCE_MARKER (y); | 3130 | CHECK_NUMBER_COERCE_MARKER (y); |
| 3169 | 3131 | ||
| @@ -3177,8 +3139,7 @@ Both X and Y must be numbers or markers. */) | |||
| 3177 | 3139 | ||
| 3178 | if (FIXNUMP (x) && FIXNUMP (y)) | 3140 | if (FIXNUMP (x) && FIXNUMP (y)) |
| 3179 | { | 3141 | { |
| 3180 | i1 = XFIXNUM (x); | 3142 | EMACS_INT i1 = XFIXNUM (x), i2 = XFIXNUM (y); |
| 3181 | i2 = XFIXNUM (y); | ||
| 3182 | 3143 | ||
| 3183 | if (i2 == 0) | 3144 | if (i2 == 0) |
| 3184 | xsignal0 (Qarith_error); | 3145 | xsignal0 (Qarith_error); |
| @@ -3189,51 +3150,21 @@ Both X and Y must be numbers or markers. */) | |||
| 3189 | if (i2 < 0 ? i1 > 0 : i1 < 0) | 3150 | if (i2 < 0 ? i1 > 0 : i1 < 0) |
| 3190 | i1 += i2; | 3151 | i1 += i2; |
| 3191 | 3152 | ||
| 3192 | XSETINT (val, i1); | 3153 | return make_fixnum (i1); |
| 3193 | } | 3154 | } |
| 3194 | else | 3155 | else |
| 3195 | { | 3156 | { |
| 3196 | mpz_t xm, ym, *xmp, *ymp; | 3157 | mpz_t *ym = bignum_integer (&mpz[1], y); |
| 3197 | mpz_t result; | 3158 | bool neg_y = mpz_sgn (*ym) < 0; |
| 3198 | int cmpr, cmpy; | 3159 | mpz_mod (mpz[0], *bignum_integer (&mpz[0], x), *ym); |
| 3199 | |||
| 3200 | if (BIGNUMP (x)) | ||
| 3201 | xmp = &XBIGNUM (x)->value; | ||
| 3202 | else | ||
| 3203 | { | ||
| 3204 | mpz_init (xm); | ||
| 3205 | mpz_set_intmax (xm, XFIXNUM (x)); | ||
| 3206 | xmp = &xm; | ||
| 3207 | } | ||
| 3208 | |||
| 3209 | if (BIGNUMP (y)) | ||
| 3210 | ymp = &XBIGNUM (y)->value; | ||
| 3211 | else | ||
| 3212 | { | ||
| 3213 | mpz_init (ym); | ||
| 3214 | mpz_set_intmax (ym, XFIXNUM (y)); | ||
| 3215 | ymp = &ym; | ||
| 3216 | } | ||
| 3217 | |||
| 3218 | mpz_init (result); | ||
| 3219 | mpz_mod (result, *xmp, *ymp); | ||
| 3220 | 3160 | ||
| 3221 | /* Fix the sign if needed. */ | 3161 | /* Fix the sign if needed. */ |
| 3222 | cmpr = mpz_sgn (result); | 3162 | int sgn_r = mpz_sgn (mpz[0]); |
| 3223 | cmpy = mpz_sgn (*ymp); | 3163 | if (neg_y ? sgn_r > 0 : sgn_r < 0) |
| 3224 | if (cmpy < 0 ? cmpr > 0 : cmpr < 0) | 3164 | mpz_add (mpz[0], mpz[0], *ym); |
| 3225 | mpz_add (result, result, *ymp); | ||
| 3226 | |||
| 3227 | val = make_integer (result); | ||
| 3228 | mpz_clear (result); | ||
| 3229 | |||
| 3230 | if (xmp == &xm) | ||
| 3231 | mpz_clear (xm); | ||
| 3232 | if (ymp == &ym) | ||
| 3233 | mpz_clear (ym); | ||
| 3234 | } | ||
| 3235 | 3165 | ||
| 3236 | return val; | 3166 | return make_integer_mpz (); |
| 3167 | } | ||
| 3237 | } | 3168 | } |
| 3238 | 3169 | ||
| 3239 | static Lisp_Object | 3170 | static Lisp_Object |
| @@ -3278,7 +3209,11 @@ Arguments may be integers, or markers converted to integers. | |||
| 3278 | usage: (logand &rest INTS-OR-MARKERS) */) | 3209 | usage: (logand &rest INTS-OR-MARKERS) */) |
| 3279 | (ptrdiff_t nargs, Lisp_Object *args) | 3210 | (ptrdiff_t nargs, Lisp_Object *args) |
| 3280 | { | 3211 | { |
| 3281 | return arith_driver (Alogand, nargs, args); | 3212 | if (nargs == 0) |
| 3213 | return make_fixnum (-1); | ||
| 3214 | Lisp_Object a = args[0]; | ||
| 3215 | CHECK_INTEGER_COERCE_MARKER (a); | ||
| 3216 | return nargs == 1 ? a : arith_driver (Alogand, nargs, args, a); | ||
| 3282 | } | 3217 | } |
| 3283 | 3218 | ||
| 3284 | DEFUN ("logior", Flogior, Slogior, 0, MANY, 0, | 3219 | DEFUN ("logior", Flogior, Slogior, 0, MANY, 0, |
| @@ -3287,7 +3222,11 @@ Arguments may be integers, or markers converted to integers. | |||
| 3287 | usage: (logior &rest INTS-OR-MARKERS) */) | 3222 | usage: (logior &rest INTS-OR-MARKERS) */) |
| 3288 | (ptrdiff_t nargs, Lisp_Object *args) | 3223 | (ptrdiff_t nargs, Lisp_Object *args) |
| 3289 | { | 3224 | { |
| 3290 | return arith_driver (Alogior, nargs, args); | 3225 | if (nargs == 0) |
| 3226 | return make_fixnum (0); | ||
| 3227 | Lisp_Object a = args[0]; | ||
| 3228 | CHECK_INTEGER_COERCE_MARKER (a); | ||
| 3229 | return nargs == 1 ? a : arith_driver (Alogior, nargs, args, a); | ||
| 3291 | } | 3230 | } |
| 3292 | 3231 | ||
| 3293 | DEFUN ("logxor", Flogxor, Slogxor, 0, MANY, 0, | 3232 | DEFUN ("logxor", Flogxor, Slogxor, 0, MANY, 0, |
| @@ -3296,7 +3235,11 @@ Arguments may be integers, or markers converted to integers. | |||
| 3296 | usage: (logxor &rest INTS-OR-MARKERS) */) | 3235 | usage: (logxor &rest INTS-OR-MARKERS) */) |
| 3297 | (ptrdiff_t nargs, Lisp_Object *args) | 3236 | (ptrdiff_t nargs, Lisp_Object *args) |
| 3298 | { | 3237 | { |
| 3299 | return arith_driver (Alogxor, nargs, args); | 3238 | if (nargs == 0) |
| 3239 | return make_fixnum (0); | ||
| 3240 | Lisp_Object a = args[0]; | ||
| 3241 | CHECK_INTEGER_COERCE_MARKER (a); | ||
| 3242 | return nargs == 1 ? a : arith_driver (Alogxor, nargs, args, a); | ||
| 3300 | } | 3243 | } |
| 3301 | 3244 | ||
| 3302 | DEFUN ("logcount", Flogcount, Slogcount, 1, 1, 0, | 3245 | DEFUN ("logcount", Flogcount, Slogcount, 1, 1, 0, |
| @@ -3310,14 +3253,13 @@ representation. */) | |||
| 3310 | 3253 | ||
| 3311 | if (BIGNUMP (value)) | 3254 | if (BIGNUMP (value)) |
| 3312 | { | 3255 | { |
| 3313 | if (mpz_sgn (XBIGNUM (value)->value) >= 0) | 3256 | mpz_t *nonneg = &XBIGNUM (value)->value; |
| 3314 | return make_fixnum (mpz_popcount (XBIGNUM (value)->value)); | 3257 | if (mpz_sgn (*nonneg) < 0) |
| 3315 | mpz_t tem; | 3258 | { |
| 3316 | mpz_init (tem); | 3259 | mpz_com (mpz[0], *nonneg); |
| 3317 | mpz_com (tem, XBIGNUM (value)->value); | 3260 | nonneg = &mpz[0]; |
| 3318 | Lisp_Object result = make_fixnum (mpz_popcount (tem)); | 3261 | } |
| 3319 | mpz_clear (tem); | 3262 | return make_fixnum (mpz_popcount (*nonneg)); |
| 3320 | return result; | ||
| 3321 | } | 3263 | } |
| 3322 | 3264 | ||
| 3323 | eassume (FIXNUMP (value)); | 3265 | eassume (FIXNUMP (value)); |
| @@ -3335,8 +3277,6 @@ If COUNT is negative, shifting is actually to the right. | |||
| 3335 | In this case, the sign bit is duplicated. */) | 3277 | In this case, the sign bit is duplicated. */) |
| 3336 | (Lisp_Object value, Lisp_Object count) | 3278 | (Lisp_Object value, Lisp_Object count) |
| 3337 | { | 3279 | { |
| 3338 | Lisp_Object val; | ||
| 3339 | |||
| 3340 | /* The negative of the minimum value of COUNT that fits into a fixnum, | 3280 | /* The negative of the minimum value of COUNT that fits into a fixnum, |
| 3341 | such that mpz_fdiv_q_exp supports -COUNT. */ | 3281 | such that mpz_fdiv_q_exp supports -COUNT. */ |
| 3342 | EMACS_INT minus_count_min = min (-MOST_NEGATIVE_FIXNUM, | 3282 | EMACS_INT minus_count_min = min (-MOST_NEGATIVE_FIXNUM, |
| @@ -3344,48 +3284,27 @@ In this case, the sign bit is duplicated. */) | |||
| 3344 | CHECK_INTEGER (value); | 3284 | CHECK_INTEGER (value); |
| 3345 | CHECK_RANGED_INTEGER (count, - minus_count_min, TYPE_MAXIMUM (mp_bitcnt_t)); | 3285 | CHECK_RANGED_INTEGER (count, - minus_count_min, TYPE_MAXIMUM (mp_bitcnt_t)); |
| 3346 | 3286 | ||
| 3347 | if (BIGNUMP (value)) | 3287 | if (XFIXNUM (count) <= 0) |
| 3348 | { | 3288 | { |
| 3349 | if (XFIXNUM (count) == 0) | 3289 | if (XFIXNUM (count) == 0) |
| 3350 | return value; | 3290 | return value; |
| 3351 | mpz_t result; | ||
| 3352 | mpz_init (result); | ||
| 3353 | if (XFIXNUM (count) > 0) | ||
| 3354 | emacs_mpz_mul_2exp (result, XBIGNUM (value)->value, XFIXNUM (count)); | ||
| 3355 | else | ||
| 3356 | mpz_fdiv_q_2exp (result, XBIGNUM (value)->value, - XFIXNUM (count)); | ||
| 3357 | val = make_integer (result); | ||
| 3358 | mpz_clear (result); | ||
| 3359 | } | ||
| 3360 | else if (XFIXNUM (count) <= 0) | ||
| 3361 | { | ||
| 3362 | /* This code assumes that signed right shifts are arithmetic. */ | ||
| 3363 | verify ((EMACS_INT) -1 >> 1 == -1); | ||
| 3364 | |||
| 3365 | EMACS_INT shift = -XFIXNUM (count); | ||
| 3366 | EMACS_INT result = (shift < EMACS_INT_WIDTH ? XFIXNUM (value) >> shift | ||
| 3367 | : XFIXNUM (value) < 0 ? -1 : 0); | ||
| 3368 | val = make_fixnum (result); | ||
| 3369 | } | ||
| 3370 | else | ||
| 3371 | { | ||
| 3372 | /* Just do the work as bignums to make the code simpler. */ | ||
| 3373 | mpz_t result; | ||
| 3374 | eassume (FIXNUMP (value)); | ||
| 3375 | mpz_init (result); | ||
| 3376 | |||
| 3377 | mpz_set_intmax (result, XFIXNUM (value)); | ||
| 3378 | |||
| 3379 | if (XFIXNUM (count) >= 0) | ||
| 3380 | emacs_mpz_mul_2exp (result, result, XFIXNUM (count)); | ||
| 3381 | else | ||
| 3382 | mpz_fdiv_q_2exp (result, result, - XFIXNUM (count)); | ||
| 3383 | 3291 | ||
| 3384 | val = make_integer (result); | 3292 | if ((EMACS_INT) -1 >> 1 == -1 && FIXNUMP (value)) |
| 3385 | mpz_clear (result); | 3293 | { |
| 3294 | EMACS_INT shift = -XFIXNUM (count); | ||
| 3295 | EMACS_INT result | ||
| 3296 | = (shift < EMACS_INT_WIDTH ? XFIXNUM (value) >> shift | ||
| 3297 | : XFIXNUM (value) < 0 ? -1 : 0); | ||
| 3298 | return make_fixnum (result); | ||
| 3299 | } | ||
| 3386 | } | 3300 | } |
| 3387 | 3301 | ||
| 3388 | return val; | 3302 | mpz_t *zval = bignum_integer (&mpz[0], value); |
| 3303 | if (XFIXNUM (count) < 0) | ||
| 3304 | mpz_fdiv_q_2exp (mpz[0], *zval, - XFIXNUM (count)); | ||
| 3305 | else | ||
| 3306 | emacs_mpz_mul_2exp (mpz[0], *zval, XFIXNUM (count)); | ||
| 3307 | return make_integer_mpz (); | ||
| 3389 | } | 3308 | } |
| 3390 | 3309 | ||
| 3391 | /* Return X ** Y as an integer. X and Y must be integers, and Y must | 3310 | /* Return X ** Y as an integer. X and Y must be integers, and Y must |
| @@ -3403,16 +3322,8 @@ expt_integer (Lisp_Object x, Lisp_Object y) | |||
| 3403 | else | 3322 | else |
| 3404 | range_error (); | 3323 | range_error (); |
| 3405 | 3324 | ||
| 3406 | mpz_t val; | 3325 | emacs_mpz_pow_ui (mpz[0], *bignum_integer (&mpz[0], x), exp); |
| 3407 | mpz_init (val); | 3326 | return make_integer_mpz (); |
| 3408 | emacs_mpz_pow_ui (val, | ||
| 3409 | (FIXNUMP (x) | ||
| 3410 | ? (mpz_set_intmax (val, XFIXNUM (x)), val) | ||
| 3411 | : XBIGNUM (x)->value), | ||
| 3412 | exp); | ||
| 3413 | Lisp_Object res = make_integer (val); | ||
| 3414 | mpz_clear (val); | ||
| 3415 | return res; | ||
| 3416 | } | 3327 | } |
| 3417 | 3328 | ||
| 3418 | DEFUN ("1+", Fadd1, Sadd1, 1, 1, 0, | 3329 | DEFUN ("1+", Fadd1, Sadd1, 1, 1, 0, |
| @@ -3422,32 +3333,12 @@ Markers are converted to integers. */) | |||
| 3422 | { | 3333 | { |
| 3423 | CHECK_NUMBER_COERCE_MARKER (number); | 3334 | CHECK_NUMBER_COERCE_MARKER (number); |
| 3424 | 3335 | ||
| 3336 | if (FIXNUMP (number)) | ||
| 3337 | return make_int (XFIXNUM (number) + 1); | ||
| 3425 | if (FLOATP (number)) | 3338 | if (FLOATP (number)) |
| 3426 | return (make_float (1.0 + XFLOAT_DATA (number))); | 3339 | return (make_float (1.0 + XFLOAT_DATA (number))); |
| 3427 | 3340 | mpz_add_ui (mpz[0], XBIGNUM (number)->value, 1); | |
| 3428 | if (BIGNUMP (number)) | 3341 | return make_integer_mpz (); |
| 3429 | { | ||
| 3430 | mpz_t num; | ||
| 3431 | mpz_init (num); | ||
| 3432 | mpz_add_ui (num, XBIGNUM (number)->value, 1); | ||
| 3433 | number = make_integer (num); | ||
| 3434 | mpz_clear (num); | ||
| 3435 | } | ||
| 3436 | else | ||
| 3437 | { | ||
| 3438 | eassume (FIXNUMP (number)); | ||
| 3439 | if (XFIXNUM (number) < MOST_POSITIVE_FIXNUM) | ||
| 3440 | XSETINT (number, XFIXNUM (number) + 1); | ||
| 3441 | else | ||
| 3442 | { | ||
| 3443 | mpz_t num; | ||
| 3444 | mpz_init (num); | ||
| 3445 | mpz_set_intmax (num, XFIXNUM (number) + 1); | ||
| 3446 | number = make_integer (num); | ||
| 3447 | mpz_clear (num); | ||
| 3448 | } | ||
| 3449 | } | ||
| 3450 | return number; | ||
| 3451 | } | 3342 | } |
| 3452 | 3343 | ||
| 3453 | DEFUN ("1-", Fsub1, Ssub1, 1, 1, 0, | 3344 | DEFUN ("1-", Fsub1, Ssub1, 1, 1, 0, |
| @@ -3457,32 +3348,12 @@ Markers are converted to integers. */) | |||
| 3457 | { | 3348 | { |
| 3458 | CHECK_NUMBER_COERCE_MARKER (number); | 3349 | CHECK_NUMBER_COERCE_MARKER (number); |
| 3459 | 3350 | ||
| 3351 | if (FIXNUMP (number)) | ||
| 3352 | return make_int (XFIXNUM (number) - 1); | ||
| 3460 | if (FLOATP (number)) | 3353 | if (FLOATP (number)) |
| 3461 | return (make_float (-1.0 + XFLOAT_DATA (number))); | 3354 | return (make_float (-1.0 + XFLOAT_DATA (number))); |
| 3462 | 3355 | mpz_sub_ui (mpz[0], XBIGNUM (number)->value, 1); | |
| 3463 | if (BIGNUMP (number)) | 3356 | return make_integer_mpz (); |
| 3464 | { | ||
| 3465 | mpz_t num; | ||
| 3466 | mpz_init (num); | ||
| 3467 | mpz_sub_ui (num, XBIGNUM (number)->value, 1); | ||
| 3468 | number = make_integer (num); | ||
| 3469 | mpz_clear (num); | ||
| 3470 | } | ||
| 3471 | else | ||
| 3472 | { | ||
| 3473 | eassume (FIXNUMP (number)); | ||
| 3474 | if (XFIXNUM (number) > MOST_NEGATIVE_FIXNUM) | ||
| 3475 | XSETINT (number, XFIXNUM (number) - 1); | ||
| 3476 | else | ||
| 3477 | { | ||
| 3478 | mpz_t num; | ||
| 3479 | mpz_init (num); | ||
| 3480 | mpz_set_intmax (num, XFIXNUM (number) - 1); | ||
| 3481 | number = make_integer (num); | ||
| 3482 | mpz_clear (num); | ||
| 3483 | } | ||
| 3484 | } | ||
| 3485 | return number; | ||
| 3486 | } | 3357 | } |
| 3487 | 3358 | ||
| 3488 | DEFUN ("lognot", Flognot, Slognot, 1, 1, 0, | 3359 | DEFUN ("lognot", Flognot, Slognot, 1, 1, 0, |
| @@ -3490,20 +3361,10 @@ DEFUN ("lognot", Flognot, Slognot, 1, 1, 0, | |||
| 3490 | (register Lisp_Object number) | 3361 | (register Lisp_Object number) |
| 3491 | { | 3362 | { |
| 3492 | CHECK_INTEGER (number); | 3363 | CHECK_INTEGER (number); |
| 3493 | if (BIGNUMP (number)) | 3364 | if (FIXNUMP (number)) |
| 3494 | { | 3365 | return make_fixnum (~XFIXNUM (number)); |
| 3495 | mpz_t value; | 3366 | mpz_com (mpz[0], XBIGNUM (number)->value); |
| 3496 | mpz_init (value); | 3367 | return make_integer_mpz (); |
| 3497 | mpz_com (value, XBIGNUM (number)->value); | ||
| 3498 | number = make_integer (value); | ||
| 3499 | mpz_clear (value); | ||
| 3500 | } | ||
| 3501 | else | ||
| 3502 | { | ||
| 3503 | eassume (FIXNUMP (number)); | ||
| 3504 | XSETINT (number, ~XFIXNUM (number)); | ||
| 3505 | } | ||
| 3506 | return number; | ||
| 3507 | } | 3368 | } |
| 3508 | 3369 | ||
| 3509 | DEFUN ("byteorder", Fbyteorder, Sbyteorder, 0, 0, 0, | 3370 | DEFUN ("byteorder", Fbyteorder, Sbyteorder, 0, 0, 0, |