14b6a78b7SSimon Schubert /* mpz_scan0 -- search for a 0 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 u>0 search since there might not be a 0
264b6a78b7SSimon Schubert bit before the end of the data. mpn_scan1 could be used for the inverted
274b6a78b7SSimon Schubert search under u<0, but usually the search won't go very far so it seems
284b6a78b7SSimon Schubert reasonable to inline that code. */
294b6a78b7SSimon Schubert
3054028e53SJohn Marino mp_bitcnt_t
mpz_scan0(mpz_srcptr u,mp_bitcnt_t starting_bit)31*d2d4b659SJohn Marino mpz_scan0 (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 /* When past end, there's an immediate 0 bit for u>=0, or no 0 bits for
434b6a78b7SSimon Schubert u<0. Notice this test picks up all cases of u==0 too. */
444b6a78b7SSimon Schubert if (starting_limb >= abs_size)
45*d2d4b659SJohn Marino return (size >= 0 ? starting_bit : ~(mp_bitcnt_t) 0);
464b6a78b7SSimon Schubert
474b6a78b7SSimon Schubert limb = *p;
484b6a78b7SSimon Schubert
494b6a78b7SSimon Schubert if (size >= 0)
504b6a78b7SSimon Schubert {
514b6a78b7SSimon Schubert /* Mask to 1 all bits before starting_bit, thus ignoring them. */
524b6a78b7SSimon Schubert limb |= (CNST_LIMB(1) << (starting_bit % GMP_NUMB_BITS)) - 1;
534b6a78b7SSimon Schubert
544b6a78b7SSimon Schubert /* Search for a limb which isn't all ones. If the end is reached then
554b6a78b7SSimon Schubert the zero bit immediately past the end is returned. */
564b6a78b7SSimon Schubert while (limb == GMP_NUMB_MAX)
574b6a78b7SSimon Schubert {
584b6a78b7SSimon Schubert p++;
594b6a78b7SSimon Schubert if (p == u_end)
6054028e53SJohn Marino return (mp_bitcnt_t) abs_size * GMP_NUMB_BITS;
614b6a78b7SSimon Schubert limb = *p;
624b6a78b7SSimon Schubert }
634b6a78b7SSimon Schubert
644b6a78b7SSimon Schubert /* Now seek low 1 bit. */
654b6a78b7SSimon Schubert limb = ~limb;
664b6a78b7SSimon Schubert }
674b6a78b7SSimon Schubert else
684b6a78b7SSimon Schubert {
694b6a78b7SSimon Schubert mp_srcptr q;
704b6a78b7SSimon Schubert
714b6a78b7SSimon Schubert /* If there's a non-zero limb before ours then we're in the ones
724b6a78b7SSimon Schubert complement region. Search from *(p-1) downwards since that might
734b6a78b7SSimon Schubert give better cache locality, and since a non-zero in the middle of a
744b6a78b7SSimon Schubert number is perhaps a touch more likely than at the end. */
754b6a78b7SSimon Schubert q = p;
764b6a78b7SSimon Schubert while (q != u_ptr)
774b6a78b7SSimon Schubert {
784b6a78b7SSimon Schubert q--;
794b6a78b7SSimon Schubert if (*q != 0)
804b6a78b7SSimon Schubert goto inverted;
814b6a78b7SSimon Schubert }
824b6a78b7SSimon Schubert
834b6a78b7SSimon Schubert /* Adjust so ~limb implied by searching for 1 bit below becomes -limb.
844b6a78b7SSimon Schubert If limb==0 here then this isn't the beginning of twos complement
854b6a78b7SSimon Schubert inversion, but that doesn't matter because limb==0 is a zero bit
864b6a78b7SSimon Schubert immediately (-1 is all ones for below). */
874b6a78b7SSimon Schubert limb--;
884b6a78b7SSimon Schubert
894b6a78b7SSimon Schubert inverted:
904b6a78b7SSimon Schubert /* Now seeking a 1 bit. */
914b6a78b7SSimon Schubert
924b6a78b7SSimon Schubert /* Mask to 0 all bits before starting_bit, thus ignoring them. */
934b6a78b7SSimon Schubert limb &= (MP_LIMB_T_MAX << (starting_bit % GMP_NUMB_BITS));
944b6a78b7SSimon Schubert
954b6a78b7SSimon Schubert if (limb == 0)
964b6a78b7SSimon Schubert {
974b6a78b7SSimon Schubert /* If the high limb is zero after masking, then no 1 bits past
984b6a78b7SSimon Schubert starting_bit. */
994b6a78b7SSimon Schubert p++;
1004b6a78b7SSimon Schubert if (p == u_end)
101*d2d4b659SJohn Marino return ~(mp_bitcnt_t) 0;
1024b6a78b7SSimon Schubert
1034b6a78b7SSimon Schubert /* Search further for a non-zero limb. The high limb is non-zero,
1044b6a78b7SSimon Schubert if nothing else. */
1054b6a78b7SSimon Schubert for (;;)
1064b6a78b7SSimon Schubert {
1074b6a78b7SSimon Schubert limb = *p;
1084b6a78b7SSimon Schubert if (limb != 0)
1094b6a78b7SSimon Schubert break;
1104b6a78b7SSimon Schubert p++;
1114b6a78b7SSimon Schubert ASSERT (p < u_end);
1124b6a78b7SSimon Schubert }
1134b6a78b7SSimon Schubert }
1144b6a78b7SSimon Schubert }
1154b6a78b7SSimon Schubert
1164b6a78b7SSimon Schubert ASSERT (limb != 0);
1174b6a78b7SSimon Schubert count_trailing_zeros (cnt, limb);
11854028e53SJohn Marino return (mp_bitcnt_t) (p - u_ptr) * GMP_NUMB_BITS + cnt;
1194b6a78b7SSimon Schubert }
120