14b6a78b7SSimon Schubert /* mpz_scan1 -- search for a 1 bit.
24b6a78b7SSimon Schubert
3*d2d4b659SJohn Marino Copyright 2000, 2001, 2002, 2004, 2012 Free Software Foundation, Inc.
44b6a78b7SSimon Schubert
54b6a78b7SSimon Schubert This file is part of the GNU MP Library.
64b6a78b7SSimon Schubert
74b6a78b7SSimon Schubert The GNU MP Library is free software; you can redistribute it and/or modify
84b6a78b7SSimon Schubert it under the terms of the GNU Lesser General Public License as published by
94b6a78b7SSimon Schubert the Free Software Foundation; either version 3 of the License, or (at your
104b6a78b7SSimon Schubert option) any later version.
114b6a78b7SSimon Schubert
124b6a78b7SSimon Schubert The GNU MP Library is distributed in the hope that it will be useful, but
134b6a78b7SSimon Schubert WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
144b6a78b7SSimon Schubert or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
154b6a78b7SSimon Schubert License for more details.
164b6a78b7SSimon Schubert
174b6a78b7SSimon Schubert You should have received a copy of the GNU Lesser General Public License
184b6a78b7SSimon Schubert along with the GNU MP Library. If not, see http://www.gnu.org/licenses/. */
194b6a78b7SSimon Schubert
204b6a78b7SSimon Schubert #include "gmp.h"
214b6a78b7SSimon Schubert #include "gmp-impl.h"
224b6a78b7SSimon Schubert #include "longlong.h"
234b6a78b7SSimon Schubert
244b6a78b7SSimon Schubert
254b6a78b7SSimon Schubert /* mpn_scan0 can't be used for the inverted u<0 search since there might not
264b6a78b7SSimon Schubert be a 0 bit before the end of the data. mpn_scan1 could be used under u>0
274b6a78b7SSimon Schubert (except when in the high limb), but usually the search won't go very far
284b6a78b7SSimon Schubert so it seems reasonable to inline that code. */
294b6a78b7SSimon Schubert
3054028e53SJohn Marino mp_bitcnt_t
mpz_scan1(mpz_srcptr u,mp_bitcnt_t starting_bit)31*d2d4b659SJohn Marino mpz_scan1 (mpz_srcptr u, mp_bitcnt_t starting_bit) __GMP_NOTHROW
324b6a78b7SSimon Schubert {
334b6a78b7SSimon Schubert mp_srcptr u_ptr = PTR(u);
344b6a78b7SSimon Schubert mp_size_t size = SIZ(u);
354b6a78b7SSimon Schubert mp_size_t abs_size = ABS(size);
364b6a78b7SSimon Schubert mp_srcptr u_end = u_ptr + abs_size;
3754028e53SJohn Marino mp_size_t starting_limb = starting_bit / GMP_NUMB_BITS;
384b6a78b7SSimon Schubert mp_srcptr p = u_ptr + starting_limb;
394b6a78b7SSimon Schubert mp_limb_t limb;
404b6a78b7SSimon Schubert int cnt;
414b6a78b7SSimon Schubert
424b6a78b7SSimon Schubert /* Past the end there's no 1 bits for u>=0, or an immediate 1 bit for u<0.
434b6a78b7SSimon Schubert Notice this test picks up any u==0 too. */
444b6a78b7SSimon Schubert if (starting_limb >= abs_size)
45*d2d4b659SJohn Marino return (size >= 0 ? ~(mp_bitcnt_t) 0 : starting_bit);
464b6a78b7SSimon Schubert
474b6a78b7SSimon Schubert limb = *p;
484b6a78b7SSimon Schubert
494b6a78b7SSimon Schubert if (size >= 0)
504b6a78b7SSimon Schubert {
514b6a78b7SSimon Schubert /* Mask to 0 all bits before starting_bit, thus ignoring them. */
524b6a78b7SSimon Schubert limb &= (MP_LIMB_T_MAX << (starting_bit % GMP_NUMB_BITS));
534b6a78b7SSimon Schubert
544b6a78b7SSimon Schubert if (limb == 0)
554b6a78b7SSimon Schubert {
564b6a78b7SSimon Schubert /* If it's the high limb which is zero after masking, then there's
574b6a78b7SSimon Schubert no 1 bits after starting_bit. */
584b6a78b7SSimon Schubert p++;
594b6a78b7SSimon Schubert if (p == u_end)
60*d2d4b659SJohn Marino return ~(mp_bitcnt_t) 0;
614b6a78b7SSimon Schubert
624b6a78b7SSimon Schubert /* Otherwise search further for a non-zero limb. The high limb is
634b6a78b7SSimon Schubert non-zero, if nothing else. */
644b6a78b7SSimon Schubert for (;;)
654b6a78b7SSimon Schubert {
664b6a78b7SSimon Schubert limb = *p;
674b6a78b7SSimon Schubert if (limb != 0)
684b6a78b7SSimon Schubert break;
694b6a78b7SSimon Schubert p++;
704b6a78b7SSimon Schubert ASSERT (p < u_end);
714b6a78b7SSimon Schubert }
724b6a78b7SSimon Schubert }
734b6a78b7SSimon Schubert }
744b6a78b7SSimon Schubert else
754b6a78b7SSimon Schubert {
764b6a78b7SSimon Schubert mp_srcptr q;
774b6a78b7SSimon Schubert
784b6a78b7SSimon Schubert /* If there's a non-zero limb before ours then we're in the ones
794b6a78b7SSimon Schubert complement region. Search from *(p-1) downwards since that might
804b6a78b7SSimon Schubert give better cache locality, and since a non-zero in the middle of a
814b6a78b7SSimon Schubert number is perhaps a touch more likely than at the end. */
824b6a78b7SSimon Schubert q = p;
834b6a78b7SSimon Schubert while (q != u_ptr)
844b6a78b7SSimon Schubert {
854b6a78b7SSimon Schubert q--;
864b6a78b7SSimon Schubert if (*q != 0)
874b6a78b7SSimon Schubert goto inverted;
884b6a78b7SSimon Schubert }
894b6a78b7SSimon Schubert
904b6a78b7SSimon Schubert if (limb == 0)
914b6a78b7SSimon Schubert {
924b6a78b7SSimon Schubert /* Skip zero limbs, to find the start of twos complement. The
934b6a78b7SSimon Schubert high limb is non-zero, if nothing else. This search is
944b6a78b7SSimon Schubert necessary so the -limb is applied at the right spot. */
954b6a78b7SSimon Schubert do
964b6a78b7SSimon Schubert {
974b6a78b7SSimon Schubert p++;
984b6a78b7SSimon Schubert ASSERT (p < u_end);
994b6a78b7SSimon Schubert limb = *p;
1004b6a78b7SSimon Schubert }
1014b6a78b7SSimon Schubert while (limb == 0);
1024b6a78b7SSimon Schubert
1034b6a78b7SSimon Schubert /* Apply twos complement, and look for a 1 bit in that. Since
1044b6a78b7SSimon Schubert limb!=0 here, also have (-limb)!=0 so there's certainly a 1
1054b6a78b7SSimon Schubert bit. */
1064b6a78b7SSimon Schubert limb = -limb;
1074b6a78b7SSimon Schubert goto got_limb;
1084b6a78b7SSimon Schubert }
1094b6a78b7SSimon Schubert
1104b6a78b7SSimon Schubert /* Adjust so ~limb implied by searching for 0 bit becomes -limb. */
1114b6a78b7SSimon Schubert limb--;
1124b6a78b7SSimon Schubert
1134b6a78b7SSimon Schubert inverted:
1144b6a78b7SSimon Schubert /* Now seeking a 0 bit. */
1154b6a78b7SSimon Schubert
1164b6a78b7SSimon Schubert /* Mask to 1 all bits before starting_bit, thus ignoring them. */
1174b6a78b7SSimon Schubert limb |= (CNST_LIMB(1) << (starting_bit % GMP_NUMB_BITS)) - 1;
1184b6a78b7SSimon Schubert
1194b6a78b7SSimon Schubert /* Search for a limb which is not all ones. If the end is reached
1204b6a78b7SSimon Schubert then the zero immediately past the end is the result. */
1214b6a78b7SSimon Schubert while (limb == GMP_NUMB_MAX)
1224b6a78b7SSimon Schubert {
1234b6a78b7SSimon Schubert p++;
1244b6a78b7SSimon Schubert if (p == u_end)
12554028e53SJohn Marino return (mp_bitcnt_t) abs_size * GMP_NUMB_BITS;
1264b6a78b7SSimon Schubert limb = *p;
1274b6a78b7SSimon Schubert }
1284b6a78b7SSimon Schubert
1294b6a78b7SSimon Schubert /* Now seeking low 1 bit. */
1304b6a78b7SSimon Schubert limb = ~limb;
1314b6a78b7SSimon Schubert }
1324b6a78b7SSimon Schubert
1334b6a78b7SSimon Schubert got_limb:
1344b6a78b7SSimon Schubert ASSERT (limb != 0);
1354b6a78b7SSimon Schubert count_trailing_zeros (cnt, limb);
13654028e53SJohn Marino return (mp_bitcnt_t) (p - u_ptr) * GMP_NUMB_BITS + cnt;
1374b6a78b7SSimon Schubert }
138