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