1 /*
  2  *  bignum_set.c
  3  *  BigMath
  4  *
  5  *  Created by Curtis Jones on 2007.08.05.
  6  *  Copyright 2007 __MyCompanyName__. All rights reserved.
  7  *
  8  */
  9 
 10 #include "bignum.h"
 11 
 12 char BIGNUM_BASE_CHAR_INV[256] =
 13 {
 14   000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000,     // 000 - 015
 15   000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000,     // 016 - 031
 16   000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000,     // 032 - 047
 17   000,   1,   2,   3,   4,   5,   6,   7,   8,   9, 000, 000, 000, 000, 000, 000,     // 048 - 063
 18   000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000,     // 064 - 079
 19   000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000,     // 080 - 095
 20   000,  10,  11,  12,  13,  14,  15,  16,  17,  18,  19,  20,  21,  22,  23,  24,     // 096 - 111
 21    25,  26,  27,  28,  29,  30,  31,  32,  33,  34,  35, 000, 000, 000, 000, 000,     // 112 - 127
 22   000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000,     // 128 - 143
 23   000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000,     // 144 - 159
 24   000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000,     // 160 - 175
 25   000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000,     // 176 - 191
 26   000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000,     // 192 - 207
 27   000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000,     // 208 - 223
 28   000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000,     // 224 - 239
 29   000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000,     // 239 - 255
 30 };
 31 
 32 /**
 33  * Sets the value of num to val. Returns a reference to num.
 34  *
 35  */
 36 bignum_t *
 37 bignum_set (bignum_t *num, u_int64_t val)
 38 {
 39   bzero(num->numb, num->size * num->sofb);
 40   
 41   BIGNUM_BASE_TYPE m1 = (val      ) & 0xFFFFFFFFull;
 42   BIGNUM_BASE_TYPE m2 = (val >> 32) & 0xFFFFFFFFull;
 43   
 44   if (m2 != 0) {
 45     __bignum_set(num, 0, m1);
 46     __bignum_set(num, 1, m2);
 47     num->oofm = 2;
 48   }
 49   else if (m1 != 0) {
 50     __bignum_set(num, 0, m1);
 51     num->oofm = 1;
 52   }
 53   else
 54     num->oofm = 0;
 55   
 56   if (val >= 0)
 57     num->sign = BIGNUM_POSITIVE;
 58   else
 59     num->sign = BIGNUM_NEGATIVE;
 60   
 61   return num;
 62 }
 63 
 64 /**
 65  * Sets the value of num to the value indicated in str, by converting the
 66  * string representation into a numeric value. This function expects str to be
 67  * null terminated.
 68  *
 69  * Maximum supported radix (at the time of writing, anyway) is thirty-six, 
 70  * which must be represented by 0-9, a-z (note that it is lower-case letters).
 71  *
 72  */
 73 bignum_t *
 74 bignum_set_str (bignum_t *num, unsigned int radix, const char *str)
 75 {
 76   int digits;
 77   const char * str_ptr;
 78   
 79   bignum_t * ret = NULL;
 80   bignum_t * multiplier = NULL;
 81   bignum_t * sum = NULL;
 82   bignum_t * radixx = NULL;
 83   bignum_t * digit = NULL;
 84   bignum_t * tmp1 = NULL;
 85   
 86   if (radix > 36)
 87     return NULL;
 88   
 89   if (str == NULL || 0 == (digits = strlen(str)))
 90     return NULL;
 91   
 92   if (NULL == (multiplier = bignum_alloc()))
 93     goto finish;
 94   
 95   if (NULL == (sum = bignum_alloc()))
 96     goto finish;
 97   
 98   if (NULL == (radixx = bignum_alloc()))
 99     goto finish;
100   
101   if (NULL == (digit = bignum_alloc()))
102     goto finish;
103   
104   if (NULL == (tmp1 = bignum_alloc()))
105     goto finish;
106   
107   bignum_set(radixx, radix);
108   bignum_set(multiplier, 1);
109   
110   str_ptr = str + digits - 1;
111   
112   // set our multiplier equal to 1
113   // for each digit in str (reversed)
114   //   get decimal value
115   //   multiply by multiplier
116   //   add to sum
117   //   multiply multiplier by radix
118   //
119   do {
120     bignum_set(digit, BIGNUM_BASE_CHAR_INV[*str_ptr]);
121     bignum_mul(tmp1, digit, multiplier);
122     bignum_add(sum, num, tmp1);
123     bignum_set_bn(num, sum);
124     bignum_mul(tmp1, multiplier, radixx);
125     bignum_set_bn(multiplier, tmp1);
126   }
127   while (--str_ptr >= str);
128   
129   ret = num;
130   
131 finish:
132   if (multiplier != NULL)
133     bignum_free(multiplier);
134     
135   if (sum != NULL)
136     bignum_free(sum);
137   
138   if (radixx != NULL)
139     bignum_free(radixx);
140   
141   if (digit != NULL)
142     bignum_free(digit);
143   
144   if (tmp1 != NULL)
145     bignum_free(tmp1);
146   
147   return ret;
148 }
149 
150 /**
151  * Sets the value of num to val. val is an array of BIGNUM_BASE_TYPEs of size
152  * cnt. val must be of the correct byte order (little endian?). Returns a 
153  * reference to num.
154  *
155  */
156 bignum_t *
157 bignum_set_ui8 (bignum_t *num, u_int64_t cnt, BIGNUM_BASE_TYPE val[])
158 {
159   u_int64_t i = cnt - 1;
160   u_int64_t j = 0;
161   
162   for (; j < cnt; --i, ++j) {
163     __bignum_set(num, j, val[i]);
164     
165     if (num->numb[j] != 0)
166       num->oofm = j + 1;
167   }
168   
169   return num;
170 }
171 
172 /**
173  * Sets the value of num1 to num2. Returns a reference to num1.
174  *
175  */
176 bignum_t *
177 bignum_set_bn (bignum_t *num1, bignum_t *num2)
178 {
179   if (num1 == NULL)
180     num1 = bignum_alloc();
181   
182   if (num1->size <= num2->oofm)
183     __bignum_grow(num1, num2->oofm);
184   
185   memcpy(num1->numb, num2->numb, num2->oofm * num2->sofb);
186   
187   num1->oofm = num2->oofm;
188   num1->sign = num2->sign;
189   
190   return num1;
191 }


syntax highlighted by Code2HTML, v. 0.9.1