UNPKG

10.2 kBtext/coffeescriptView Raw
1
2
3
4#double convert_rational_to_double(U *)
5#double convert_bignum_to_double(unsigned int *)
6#int ge(unsigned int *, unsigned int *, int)
7
8
9
10mint = (a) ->
11 return bigInt a
12
13
14# b is +1 or -1, a is a bigint
15setSignTo = (a,b) ->
16 if a.isPositive()
17 if b < 0
18 return a.multiply bigInt -1
19 else
20 # a is negative
21 if b > 0
22 return a.multiply bigInt -1
23 return a
24
25
26makeSignSameAs = (a,b) ->
27 if a.isPositive()
28 if b.isNegative()
29 return a.multiply bigInt -1
30 else
31 # a is negative
32 if b.isPositive()
33 return a.multiply bigInt -1
34 return a
35
36makePositive = (a) ->
37 if a.isNegative()
38 return a.multiply bigInt -1
39 return a
40
41# n is an int
42###
43mtotal = 0
44MP_MIN_SIZE = 2
45MP_MAX_FREE = 1000
46
47mnew = (n) ->
48 if (n < MP_MIN_SIZE)
49 n = MP_MIN_SIZE
50 if (n == MP_MIN_SIZE && mfreecount)
51 p = free_stack[--mfreecount]
52 else
53 p = [] #(unsigned int *) malloc((n + 3) * sizeof (int))
54 #if (p == 0)
55 # stop("malloc failure")
56 p[0] = n
57 mtotal += n
58 return p[3]
59###
60
61# p is the index of array of ints
62# !!! array wasn't passed here
63###
64free_stack = []
65
66mfree = (array, p) ->
67 p -= 3
68 mtotal -= array[p]
69 if (array[p] == MP_MIN_SIZE && mfreecount < MP_MAX_FREE)
70 free_stack[mfreecount++] = p
71 else
72 free(p)
73###
74
75# convert int to bignum
76
77# n is an int
78###
79mint = (n) ->
80 p = mnew(1)
81 if (n < 0)
82 # !!! this is FU
83 # MSIGN(p) = -1
84 fu = true
85 else
86 # !!! this is FU
87 #MSIGN(p) = 1
88 fu = true
89 # !!! this is FU
90 #MLENGTH(p) = 1
91 p[0] = Math.abs(n)
92 return p
93###
94
95# copy bignum
96
97# a is an array of ints
98###
99mcopy = (a) ->
100 #unsigned int *b
101
102 b = mnew(MLENGTH(a))
103
104 # !!! fu
105 #MSIGN(b) = MSIGN(a)
106 #MLENGTH(b) = MLENGTH(a)
107
108 for i in [0...MLENGTH(a)]
109 b[i] = a[i]
110
111 return b
112###
113
114
115###
116#
117# ge not invoked from anywhere - is you need ge
118# just use the bigNum's ge implementation
119# leaving it here just in case I decide to backport to C
120#
121# a >= b ?
122# and and b arrays of ints, len is an int
123ge = (a, b, len) ->
124 i = 0
125 for i in [0...len]
126 if (a[i] == b[i])
127 continue
128 else
129 break
130 if (a[i] >= b[i])
131 return 1
132 else
133 return 0
134###
135
136add_numbers = ->
137 a = 1.0
138 b = 1.0
139
140 #if DEBUG then console.log("add_numbers adding numbers: " + print_list(stack[tos - 1]) + " and " + print_list(stack[tos - 2]))
141
142 if (isrational(stack[tos - 1]) && isrational(stack[tos - 2]))
143 qadd()
144 return
145
146 save()
147
148 p2 = pop()
149 p1 = pop()
150
151 if (isdouble(p1))
152 a = p1.d
153 else
154 a = convert_rational_to_double(p1)
155
156 if (isdouble(p2))
157 b = p2.d
158 else
159 b = convert_rational_to_double(p2)
160
161 theResult = a+b
162 push_double(theResult)
163
164 restore()
165
166subtract_numbers = ->
167 a = 0.0
168 b = 0.0
169
170 if (isrational(stack[tos - 1]) && isrational(stack[tos - 2]))
171 qsub()
172 return
173
174 save()
175
176 p2 = pop()
177 p1 = pop()
178
179 if (isdouble(p1))
180 a = p1.d
181 else
182 a = convert_rational_to_double(p1)
183
184 if (isdouble(p2))
185 b = p2.d
186 else
187 b = convert_rational_to_double(p2)
188
189 push_double(a - b)
190
191 restore()
192
193multiply_numbers = ->
194 a = 0.0
195 b = 0.0
196
197 if (isrational(stack[tos - 1]) && isrational(stack[tos - 2]))
198 qmul()
199 return
200
201 save()
202
203 p2 = pop()
204 p1 = pop()
205
206 if (isdouble(p1))
207 a = p1.d
208 else
209 a = convert_rational_to_double(p1)
210
211 if (isdouble(p2))
212 b = p2.d
213 else
214 b = convert_rational_to_double(p2)
215
216 push_double(a * b)
217
218 restore()
219
220divide_numbers = ->
221 a = 0.0
222 b = 0.0
223
224 if (isrational(stack[tos - 1]) && isrational(stack[tos - 2]))
225 qdiv()
226 return
227
228 save()
229
230 p2 = pop()
231 p1 = pop()
232
233 if (iszero(p2))
234 stop("divide by zero")
235
236 if (isdouble(p1))
237 a = p1.d
238 else
239 a = convert_rational_to_double(p1)
240
241 if (isdouble(p2))
242 b = p2.d
243 else
244 b = convert_rational_to_double(p2)
245
246 push_double(a / b)
247
248 restore()
249
250invert_number = ->
251 #unsigned int *a, *b
252
253 save()
254
255 p1 = pop()
256
257 if (iszero(p1))
258 stop("divide by zero")
259
260 if (isdouble(p1))
261 push_double(1 / p1.d)
262 restore()
263 return
264
265 a = bigInt(p1.q.a)
266 b = bigInt(p1.q.b)
267
268 b = makeSignSameAs(b,a)
269 a = setSignTo(a,1)
270
271 p1 = new U()
272 p1.k = NUM
273 p1.q.a = b
274 p1.q.b = a
275
276 push(p1)
277
278 restore()
279
280# a and b are Us
281compare_rationals = (a, b) ->
282 t = 0
283 #unsigned int *ab, *ba
284 ab = mmul(a.q.a, b.q.b)
285 ba = mmul(a.q.b, b.q.a)
286 t = mcmp(ab, ba)
287 return t
288
289# a and b are Us
290compare_numbers = (a,b) ->
291 x = 0.0
292 y = 0.0
293 if (isrational(a) && isrational(b))
294 return compare_rationals(a, b)
295 if (isdouble(a))
296 x = a.d
297 else
298 x = convert_rational_to_double(a)
299 if (isdouble(b))
300 y = b.d
301 else
302 y = convert_rational_to_double(b)
303 if (x < y)
304 return -1
305 if (x > y)
306 return 1
307 return 0
308
309negate_number = ->
310 save()
311 p1 = pop()
312 if (iszero(p1))
313 push(p1)
314 restore()
315 return
316
317 switch (p1.k)
318 when NUM
319 p2 = new U()
320 p2.k = NUM
321 p2.q.a = bigInt(p1.q.a.multiply(bigInt.minusOne))
322 p2.q.b = bigInt(p1.q.b)
323 push(p2)
324 when DOUBLE
325 push_double(-p1.d)
326 else
327 stop("bug caught in mp_negate_number")
328 restore()
329
330bignum_truncate = ->
331 #unsigned int *a
332
333 save()
334
335 p1 = pop()
336
337 a = mdiv(p1.q.a, p1.q.b)
338
339 p1 = new U()
340
341 p1.k = NUM
342
343 p1.q.a = a
344 p1.q.b = bigInt(1)
345
346 push(p1)
347
348 restore()
349
350mp_numerator = ->
351 save()
352
353 p1 = pop()
354
355 if (p1.k != NUM)
356 push(one)
357 restore()
358 return
359
360 p2 = new U()
361
362 p2.k = NUM
363
364 p2.q.a = bigInt(p1.q.a)
365 p2.q.b = bigInt(1)
366
367 push(p2)
368
369 restore()
370
371mp_denominator = ->
372 save()
373
374 p1 = pop()
375
376 if (p1.k != NUM)
377 push(one)
378 restore()
379 return
380
381 p2 = new U()
382 p2.k = NUM
383 p2.q.a = bigInt(p1.q.b)
384 p2.q.b = bigInt(1)
385
386 push(p2)
387
388 restore()
389
390# expo is an integer
391bignum_power_number = (expo) ->
392 #unsigned int *a, *b, *t
393
394 save()
395
396 p1 = pop()
397
398 a = mpow(p1.q.a, Math.abs(expo))
399 b = mpow(p1.q.b, Math.abs(expo))
400
401 if (expo < 0)
402 # swap a and b
403 t = a
404 a = b
405 b = t
406
407 a = makeSignSameAs(a,b)
408 b = setSignTo(b,1)
409
410 p1 = new U()
411
412 p1.k = NUM
413
414 p1.q.a = a
415 p1.q.b = b
416
417 push(p1)
418
419 restore()
420
421# p an array of ints
422convert_bignum_to_double = (p) ->
423 return p.toJSNumber()
424
425# p is a U
426convert_rational_to_double = (p) ->
427 if !p.q?
428 debugger
429 quotientAndRemainder = p.q.a.divmod(p.q.b)
430 result = quotientAndRemainder.quotient + quotientAndRemainder.remainder / p.q.b.toJSNumber()
431
432 return result
433
434# n an integer
435push_integer = (n) ->
436 if DEBUG then console.log "pushing integer " + n
437 save()
438 p1 = new U()
439 p1.k = NUM
440 p1.q.a = bigInt(n)
441 p1.q.b = bigInt(1)
442 push(p1)
443 restore()
444
445# d a double
446push_double = (d) ->
447 save()
448 p1 = new U()
449 p1.k = DOUBLE
450 p1.d = d
451 push(p1)
452 restore()
453
454# a,b parts of a rational
455push_rational = (a,b) ->
456 ###
457 save()
458 p1 = new U()
459 p1.k = NUM
460 p1.q.a = bigInt(a)
461 p1.q.b = bigInt(b)
462 ## FIXME -- normalize ##
463 push(p1)
464 restore()
465 ###
466
467 p = new U()
468 p.k = NUM
469 p.q.a = bigInt(a)
470 p.q.b = bigInt(b)
471 push(p)
472
473pop_integer = ->
474 n = NaN
475
476 save()
477
478 p1 = pop()
479
480 switch (p1.k)
481
482 when NUM
483 if (isinteger(p1) && p1.q.a.isSmall)
484 n = p1.q.a.toJSNumber()
485
486 when DOUBLE
487 if DEBUG
488 console.log "popping integer but double is found"
489 if Math.floor(p1.d) == p1.d
490 if DEBUG
491 console.log "...altough it's an integer"
492 n = p1.d
493
494 restore()
495 return n
496
497# p is a U, flag is an int
498print_double = (p,flag) ->
499 accumulator = ""
500 buf = doubleToReasonableString(p.d)
501 if (flag == 1 && buf == '-')
502 accumulator += print_str(buf + 1)
503 else
504 accumulator += print_str(buf)
505 return accumulator
506
507# s is a string
508bignum_scan_integer = (s) ->
509 #unsigned int *a
510 #char sign
511
512 save()
513 scounter = 0
514
515 sign_ = s[scounter]
516
517 if (sign_ == '+' || sign_ == '-')
518 scounter++
519
520 # !!!! some mess in here, added an argument
521 a = bigInt(s.substring(scounter))
522
523 p1 = new U()
524
525 p1.k = NUM
526
527 p1.q.a = a
528 p1.q.b = bigInt(1)
529
530 push(p1)
531
532 if (sign_ == '-')
533 negate()
534
535 restore()
536
537# s a string
538bignum_scan_float = (s) ->
539 push_double(parseFloat(s))
540
541# gives the capability of printing the unsigned
542# value. This is handy because printing of the sign
543# might be taken care of "upstream"
544# e.g. when printing a base elevated to a negative exponent
545# prints the inverse of the base powered to the unsigned
546# exponent.
547# p is a U
548print_number = (p, signed) ->
549 accumulator = ""
550
551 denominatorString = ""
552 buf = ""
553 switch (p.k)
554 when NUM
555 aAsString = p.q.a.toString()
556 if !signed
557 if aAsString[0] == "-"
558 aAsString = aAsString.substring(1)
559
560 if (printMode == PRINTMODE_LATEX and isfraction(p))
561 aAsString = "\\frac{"+aAsString+"}{"
562
563 accumulator += aAsString
564
565 if (isfraction(p))
566 if printMode != PRINTMODE_LATEX
567 accumulator += ("/")
568 denominatorString = p.q.b.toString()
569 if printMode == PRINTMODE_LATEX then denominatorString += "}"
570
571 accumulator += denominatorString
572
573 when DOUBLE
574 aAsString = doubleToReasonableString(p.d)
575 if !signed
576 if aAsString[0] == "-"
577 aAsString = aAsString.substring(1)
578
579 accumulator += aAsString
580
581 return accumulator
582
583gcd_numbers = ->
584 save()
585
586 p2 = pop()
587 p1 = pop()
588
589# if (!isinteger(p1) || !isinteger(p2))
590# stop("integer args expected for gcd")
591
592 p3 = new U()
593
594 p3.k = NUM
595
596 p3.q.a = mgcd(p1.q.a, p2.q.a)
597 p3.q.b = mgcd(p1.q.b, p2.q.b)
598
599 p3.q.a = setSignTo(p3.q.a,1)
600
601 push(p3)
602
603 restore()
604
605pop_double = ->
606 d = 0.0
607 save()
608 p1 = pop()
609 switch (p1.k)
610 when NUM
611 d = convert_rational_to_double(p1)
612 when DOUBLE
613 d = p1.d
614 else
615 d = 0.0
616 restore()
617 return d
618
619bignum_float = ->
620 d = 0.0
621 d = convert_rational_to_double(pop())
622 push_double(d)
623
624#static unsigned int *__factorial(int)
625
626# n is an int
627bignum_factorial = (n) ->
628 save()
629 p1 = new U()
630 p1.k = NUM
631 p1.q.a = __factorial(n)
632 p1.q.b = bigInt(1)
633 push(p1)
634 restore()
635
636# n is an int
637__factorial = (n) ->
638 i = 0
639 #unsigned int *a, *b, *t
640
641 if (n == 0 || n == 1)
642 a = bigInt(1)
643 return a
644
645 a = bigInt(2)
646
647 b = bigInt(0)
648
649 if 3 <= n
650 for i in [3..n]
651 b = bigInt(i)
652 t = mmul(a, b)
653 a = t
654
655
656 return a
657
658mask = [
659 0x00000001,
660 0x00000002,
661 0x00000004,
662 0x00000008,
663 0x00000010,
664 0x00000020,
665 0x00000040,
666 0x00000080,
667 0x00000100,
668 0x00000200,
669 0x00000400,
670 0x00000800,
671 0x00001000,
672 0x00002000,
673 0x00004000,
674 0x00008000,
675 0x00010000,
676 0x00020000,
677 0x00040000,
678 0x00080000,
679 0x00100000,
680 0x00200000,
681 0x00400000,
682 0x00800000,
683 0x01000000,
684 0x02000000,
685 0x04000000,
686 0x08000000,
687 0x10000000,
688 0x20000000,
689 0x40000000,
690 0x80000000,
691]
692
693# unsigned int *x, unsigned int k
694mp_set_bit = (x, k) ->
695 console.log "not implemented yet"
696 debugger
697 x[k / 32] |= mask[k % 32]
698
699# unsigned int *x, unsigned int k
700mp_clr_bit = (x,k) ->
701 console.log "not implemented yet"
702 debugger
703 x[k / 32] &= ~mask[k % 32]
704
705# unsigned int *a
706mshiftright = (a) ->
707 a = a.shiftRight()
708