xref: /dflybsd-src/contrib/gmp/mpz/scan1.c (revision d365564473a20a528d07c59cad8ee2f4bea5546f)
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