FIX BUILD (with GHC 6.2.x): System.Directory.Internals is no more
[ghc-hetmet.git] / rts / gmp / mpn / generic / set_str.c
1 /* mpn_set_str (mp_ptr res_ptr, const char *str, size_t str_len, int base)
2    -- Convert a STR_LEN long base BASE byte string pointed to by STR to a
3    limb vector pointed to by RES_PTR.  Return the number of limbs in
4    RES_PTR.
5
6 Copyright (C) 1991, 1992, 1993, 1994, 1996, 2000 Free Software Foundation,
7 Inc.
8
9 This file is part of the GNU MP Library.
10
11 The GNU MP Library is free software; you can redistribute it and/or modify
12 it under the terms of the GNU Lesser General Public License as published by
13 the Free Software Foundation; either version 2.1 of the License, or (at your
14 option) any later version.
15
16 The GNU MP Library is distributed in the hope that it will be useful, but
17 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
18 or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
19 License for more details.
20
21 You should have received a copy of the GNU Lesser General Public License
22 along with the GNU MP Library; see the file COPYING.LIB.  If not, write to
23 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
24 MA 02111-1307, USA. */
25
26 #include "gmp.h"
27 #include "gmp-impl.h"
28
29 mp_size_t
30 #if __STDC__
31 mpn_set_str (mp_ptr xp, const unsigned char *str, size_t str_len, int base)
32 #else
33 mpn_set_str (xp, str, str_len, base)
34      mp_ptr xp;
35      const unsigned char *str;
36      size_t str_len;
37      int base;
38 #endif
39 {
40   mp_size_t size;
41   mp_limb_t big_base;
42   int indigits_per_limb;
43   mp_limb_t res_digit;
44
45   big_base = __mp_bases[base].big_base;
46   indigits_per_limb = __mp_bases[base].chars_per_limb;
47
48 /*   size = str_len / indigits_per_limb + 1;  */
49
50   size = 0;
51
52   if ((base & (base - 1)) == 0)
53     {
54       /* The base is a power of 2.  Read the input string from
55          least to most significant character/digit.  */
56
57       const unsigned char *s;
58       int next_bitpos;
59       int bits_per_indigit = big_base;
60
61       res_digit = 0;
62       next_bitpos = 0;
63
64       for (s = str + str_len - 1; s >= str; s--)
65         {
66           int inp_digit = *s;
67
68           res_digit |= (mp_limb_t) inp_digit << next_bitpos;
69           next_bitpos += bits_per_indigit;
70           if (next_bitpos >= BITS_PER_MP_LIMB)
71             {
72               xp[size++] = res_digit;
73               next_bitpos -= BITS_PER_MP_LIMB;
74               res_digit = inp_digit >> (bits_per_indigit - next_bitpos);
75             }
76         }
77
78       if (res_digit != 0)
79         xp[size++] = res_digit;
80     }
81   else
82     {
83       /* General case.  The base is not a power of 2.  */
84
85       size_t i;
86       int j;
87       mp_limb_t cy_limb;
88
89       for (i = indigits_per_limb; i < str_len; i += indigits_per_limb)
90         {
91           res_digit = *str++;
92           if (base == 10)
93             { /* This is a common case.
94                  Help the compiler to avoid multiplication.  */
95               for (j = 1; j < indigits_per_limb; j++)
96                 res_digit = res_digit * 10 + *str++;
97             }
98           else
99             {
100               for (j = 1; j < indigits_per_limb; j++)
101                 res_digit = res_digit * base + *str++;
102             }
103
104           if (size == 0)
105             {
106               if (res_digit != 0)
107                 {
108                   xp[0] = res_digit;
109                   size = 1;
110                 }
111             }
112           else
113             {
114               cy_limb = mpn_mul_1 (xp, xp, size, big_base);
115               cy_limb += mpn_add_1 (xp, xp, size, res_digit);
116               if (cy_limb != 0)
117                 xp[size++] = cy_limb;
118             }
119         }
120
121       big_base = base;
122       res_digit = *str++;
123       if (base == 10)
124         { /* This is a common case.
125              Help the compiler to avoid multiplication.  */
126           for (j = 1; j < str_len - (i - indigits_per_limb); j++)
127             {
128               res_digit = res_digit * 10 + *str++;
129               big_base *= 10;
130             }
131         }
132       else
133         {
134           for (j = 1; j < str_len - (i - indigits_per_limb); j++)
135             {
136               res_digit = res_digit * base + *str++;
137               big_base *= base;
138             }
139         }
140
141       if (size == 0)
142         {
143           if (res_digit != 0)
144             {
145               xp[0] = res_digit;
146               size = 1;
147             }
148         }
149       else
150         {
151           cy_limb = mpn_mul_1 (xp, xp, size, big_base);
152           cy_limb += mpn_add_1 (xp, xp, size, res_digit);
153           if (cy_limb != 0)
154             xp[size++] = cy_limb;
155         }
156     }
157
158   return size;
159 }