@@ -109,3 +109,122 @@ test "validate digits in string parsing (https://github.com/def-/nim-bigints/iss
109
109
discard initBigInt (" 2" , 2 )
110
110
expect ValueError :
111
111
discard initBigInt (" z" , 35 )
112
+
113
+ test " empty limbs when uninitialized (https://github.com/def-/nim-bigints/issues/26)" :
114
+ # reported issue has an example about multiplication and it is due to a call to a.limbs[0] for an uninitialized a: BigInt
115
+ # besides multiplication, one could look at appearances of [0] in source to find possible failures
116
+ # failures bound to reaching a line with [0] are fatal
117
+ # besides appearances of [0], also logic implemented through a.limbs.len might (and indeed does) show error
118
+ # logic around sign might also play a role
119
+ var
120
+ zeroEmpty: BigInt # should be treated as zero, same with -zeroEmpty
121
+ let
122
+ zeroInt32: int32 = 0
123
+ oneInt32: int32 = 1
124
+ bigOne: BigInt = initBigInt (@ [0 .uint32 , 1 ])
125
+
126
+ # unsignedCmp(a: BigInt, b: int32) has [0]; used by public cmp and <
127
+ # never reached in the following cases (no fatal), since it cannot be reached (see comment in code)
128
+ # still, errors can be found in comparing zero to zero
129
+ check zeroEmpty < oneInt32 # ok
130
+ check zeroEmpty > - oneInt32 # ok
131
+ check - zeroEmpty < oneInt32 # ok
132
+ check - zeroEmpty > - oneInt32 # ok
133
+ check not (zeroEmpty < zeroInt32) # error: fixed
134
+ check not (zeroEmpty > zeroInt32) # ok
135
+ check not (- zeroEmpty < zeroInt32) # error: fixed
136
+ check not (- zeroEmpty > zeroInt32) # ok
137
+ check zeroEmpty == zeroInt32 # error: fixed
138
+ check - zeroEmpty == zeroInt32 # error: fixed
139
+
140
+ # this came up in the above testing and can be though as secondary effect of unitialization (fix in negate?)
141
+ check $ zero == " 0" # ok
142
+ check $ zeroEmpty == " 0" # ok
143
+ check $ (- zeroEmpty) == " 0" # error: fixed
144
+
145
+ # unsignedCmp(a, b: BigInt) has no [0] but it has logic with limbs.len
146
+ check zeroEmpty < one # ok
147
+ check zeroEmpty > - one # ok
148
+ check - zeroEmpty < one # ok
149
+ check - zeroEmpty > - one # ok
150
+ check not (zeroEmpty < zeroInt32) # error: fixed
151
+ check not (zeroEmpty > zeroInt32) # ok
152
+ check not (zeroEmpty < zero) # error: fixed
153
+ check not (zeroEmpty > zero) # ok
154
+ check zeroEmpty == zero # error: fixed
155
+ check - zeroEmpty == zero # error: fixed
156
+
157
+ # proc unsignedAdditionInt(a: var BigInt, b: BigInt, c: int32)
158
+ check zeroEmpty + 1 .int32 == one # fixed: fatal[IndexError] in bigints.nim(181) unsignedAdditionInt
159
+ check - zeroEmpty + 1 .int32 == one # fixed: fatal[IndexError] in bigints.nim(245) unsignedSubtractionInt
160
+ check zeroEmpty + (- 1 ).int32 == - one # fixed: fatal[IndexError] in bigints.nim(245) unsignedSubtractionInt
161
+ check - zeroEmpty + (- 1 ).int32 == - one # fixed: fatal[IndexError] in bigints.nim(181) unsignedAdditionInt
162
+
163
+ # proc unsignedAddition(a: var BigInt, b, c: BigInt)
164
+ check zeroEmpty + one == one # ok
165
+ check one + zeroEmpty == one # ok
166
+ check - zeroEmpty + one == one # ok
167
+ check one + - zeroEmpty == one # ok
168
+ check zeroEmpty + zeroEmpty == zero # ok
169
+ check - zeroEmpty + zeroEmpty == zero # ok
170
+ check - zeroEmpty + - zeroEmpty == zero # ok
171
+ check zeroEmpty + - zeroEmpty == zero # ok
172
+ check bigOne + zeroEmpty == bigOne # ok
173
+ check bigOne + - zeroEmpty == bigOne # ok
174
+ check zeroEmpty + bigOne == bigOne # ok
175
+ check - zeroEmpty + bigOne == bigOne # ok
176
+ check - bigOne + zeroEmpty == - bigOne # ok
177
+ check - bigOne + - zeroEmpty == - bigOne # ok
178
+ check zeroEmpty + - bigOne == - bigOne # ok
179
+ check - zeroEmpty + - bigOne == - bigOne # ok
180
+
181
+ # proc unsignedSubtractionInt(a: var BigInt, b: BigInt, c: int32)
182
+ check zeroEmpty - 1 .int32 == - one # fixed: fatal[IndexError] in bigints.nim(245) unsignedSubtractionInt
183
+ check - zeroEmpty - 1 .int32 == - one # fixed: fatal[IndexError] in bigints.nim(181) unsignedAdditionInt
184
+ check zeroEmpty - (- 1 ).int32 == one # fixed: fatal[IndexError] in bigints.nim(181) unsignedAdditionInt
185
+ check - zeroEmpty - (- 1 ).int32 == one # fixed: fatal[IndexError] in bigints.nim(245) unsignedSubtractionInt
186
+
187
+ # proc unsignedSubtraction(a: var BigInt, b, c: BigInt)
188
+ check zeroEmpty - one == - one # ok
189
+ check one - zeroEmpty == one # ok
190
+ check - zeroEmpty - one == - one # ok
191
+ check one - - zeroEmpty == one # ok
192
+ check zeroEmpty - zeroEmpty == zero # ok
193
+ check - zeroEmpty - zeroEmpty == zero # ok
194
+ check - zeroEmpty - - zeroEmpty == zero # ok
195
+ check zeroEmpty - - zeroEmpty == zero # ok
196
+ check bigOne - zeroEmpty == bigOne # ok
197
+ check bigOne - - zeroEmpty == bigOne # ok
198
+ check zeroEmpty - bigOne == - bigOne # ok
199
+ check - zeroEmpty - bigOne == - bigOne # ok
200
+ check - bigOne - zeroEmpty == - bigOne # ok
201
+ check - bigOne - - zeroEmpty == - bigOne # ok
202
+ check zeroEmpty - - bigOne == bigOne # ok
203
+ check - zeroEmpty - - bigOne == bigOne # ok
204
+
205
+ # multiplication
206
+ check zeroEmpty * 1 .int32 == zero
207
+ check - zeroEmpty * 1 .int32 == zero
208
+ check zeroEmpty * one == zero
209
+ check - zeroEmpty * one == zero
210
+ check one * zeroEmpty == zero
211
+ check one * - zeroEmpty == zero
212
+
213
+ # https://github.com/def-/nim-bigints/issues/26
214
+ block :
215
+ var
216
+ a: BigInt
217
+ b: BigInt = 12 .initBigInt
218
+
219
+ check a* b == 0
220
+
221
+ # division does not have issues, but let's add some checks
222
+ check zeroEmpty div one == zero
223
+ check - zeroEmpty div one == zero
224
+ check zeroEmpty mod one == zero
225
+ check - zeroEmpty mod one == zero
226
+
227
+ check zeroEmpty div 1 .int32 == zero
228
+ check - zeroEmpty div 1 .int32 == zero
229
+ check zeroEmpty mod 1 .int32 == zero
230
+ check - zeroEmpty mod 1 .int32 == zero
0 commit comments