You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

88 lines
3.0 KiB

25 years ago
  1. // ash().
  2. // General includes.
  3. #include "cl_sysdep.h"
  4. // Specification.
  5. #include "cl_integer.h"
  6. // Implementation.
  7. #include "cl_I.h"
  8. #include "cl_DS.h"
  9. #include "cl_I_ash.h"
  10. const cl_I ash (const cl_I& x, sintL y)
  11. {
  12. // Methode:
  13. // x = 0 -> 0 als Ergebnis
  14. // y = 0 -> x als Ergebnis
  15. // y > 0 -> y = intDsize*k + i, j=k+(1 falls i>0, 0 falls i=0).
  16. // j W�rter mehr reservieren, k Nullw�rter, dann �bertragen,
  17. // bei i>0: um i Bits links schieben (i=1 geht einfacher).
  18. // y < 0 -> y <= - intDsize * (L�nge(A0) in Digits) -> Ergebnis = 0 oder -1.
  19. // Sonst: -y = intDsize*k + i mit k<L�nge(A0).
  20. // �bertrage die (L�nge(A0)-k) MSDigits,
  21. // falls i>0: schiebe sie um i Bits nach rechts (i=1 geht einfacher).
  22. if (zerop(x))
  23. return 0; // x=0 -> 0 als Ergebnis
  24. if (y == 0)
  25. return x; // y=0 -> x als Ergebnis
  26. CL_ALLOCA_STACK;
  27. if (y >= 0) {
  28. // y>0
  29. var uintL y_ = (uintL)y;
  30. var uintL i = y_%intDsize; // i = y mod intDsize, >=0, <intDsize
  31. var uintL k = floor(y_,intDsize); // k = y div intDsize, >=0, <2^intCsize
  32. var uintD* LSDptr;
  33. var uintC len;
  34. var const uintD* x_LSDptr;
  35. I_to_NDS_nocopy(x, ,len=,x_LSDptr=,cl_false,); // DS zu x bilden.
  36. if (k >= (uintC)(~(uintC)len)) // kann len+k+1 �berlauf geben?
  37. { cl_ash_error(y); } // ja -> Fehler
  38. num_stack_alloc_1(len+k,,LSDptr=);
  39. LSDptr = clear_loop_lsp(LSDptr,k); // k Nulldigits
  40. {var uintD* MSDptr = copy_loop_lsp(x_LSDptr,LSDptr,len);
  41. // Nun ist MSDptr/len/LSDptr die DS zu x.
  42. // Oberhalb von ihr liegen k Nulldigits, unterhalb ist 1 Digit Platz.
  43. // MSDptr/len+k/.. ist jetzt die Gesamt-DS.
  44. // Noch um i Bits nach links schieben:
  45. if (!(i==0)) // Bei i>0
  46. { // noch ein weiteres Digit dazunehmen (Vorzeichen)
  47. {var uintD sign = sign_of_sintD(mspref(MSDptr,0));
  48. lsprefnext(MSDptr) = sign;
  49. len++;
  50. }
  51. // Schiebeschleife: die unteren len Digits um i Bits schieben
  52. if (i==1)
  53. { shift1left_loop_lsp(LSDptr,len); }
  54. else
  55. { shiftleft_loop_lsp(LSDptr,len,i,0); }
  56. }
  57. return DS_to_I(MSDptr,len+k);
  58. }
  59. } else {
  60. // y<0
  61. var uintL y_ = (uintL)(-y); // Wert von -y, >0
  62. var uintL i = y_%intDsize; // i = (-y) mod intDsize, >=0, <intDsize
  63. var uintL k = floor(y_,intDsize); // k = (-y) div intDsize, >=0
  64. // DS zu x bilden:
  65. var uintD* MSDptr;
  66. var uintC len;
  67. I_to_NDS(x, MSDptr=,len=,); // DS zu x bilden.
  68. if (k>=len) goto sign; // -y >= intDsize*len -> Vorzeichen von x zur�ck
  69. len -= k; // rechte k Digits einfach streichen
  70. // Noch ist len>0. Um i Bits nach rechts schieben:
  71. if (!(i==0)) // Bei i>0:
  72. { // Schiebe len Digits ab MSDptr um i Bits nach rechts:
  73. if (i==1)
  74. { shift1right_loop_msp(MSDptr,len,sign_of_sintD(mspref(MSDptr,0))); }
  75. else
  76. { shiftrightsigned_loop_msp(MSDptr,len,i); }
  77. }
  78. return DS_to_I(MSDptr,len);
  79. }
  80. sign: // Ergebnis ist 0, falls x>=0, und -1, falls x<0:
  81. return (minusp(x) ? cl_I(-1) : cl_I(0));
  82. }