long-decimal 0.00.12 → 0.00.13

Sign up to get free protection for your applications and to get access to all the features.
Files changed (293) hide show
  1. data/README +69 -18
  2. data/Rakefile +3 -3
  3. data/VERSION +1 -1
  4. data/doc/classes/LongDecimalRoundingMode.html +2 -2
  5. data/doc/classes/LongDecimalRoundingMode/RoundingModeClass.html +2 -2
  6. data/doc/classes/LongDecimalRoundingMode/RoundingModeClass.src/M000135.html +1 -1
  7. data/doc/classes/LongMath.html +2 -2
  8. data/doc/classes/LongMath.src/M000001.html +1 -1
  9. data/doc/classes/LongMath.src/M000002.html +1 -1
  10. data/doc/classes/LongMath.src/M000003.html +1 -1
  11. data/doc/classes/LongMath.src/M000004.html +1 -1
  12. data/doc/classes/LongMath.src/M000005.html +1 -1
  13. data/doc/classes/LongMath.src/M000006.html +1 -1
  14. data/doc/classes/LongMath.src/M000007.html +1 -1
  15. data/doc/classes/LongMath.src/M000008.html +1 -1
  16. data/doc/classes/LongMath.src/M000009.html +1 -1
  17. data/doc/classes/LongMath.src/M000010.html +1 -1
  18. data/doc/classes/LongMath.src/M000011.html +1 -1
  19. data/doc/classes/LongMath.src/M000012.html +1 -1
  20. data/doc/classes/LongMath.src/M000013.html +1 -1
  21. data/doc/classes/LongMath.src/M000014.html +1 -1
  22. data/doc/classes/LongMath.src/M000015.html +1 -1
  23. data/doc/classes/LongMath.src/M000016.html +1 -1
  24. data/doc/classes/LongMath.src/M000017.html +1 -1
  25. data/doc/classes/LongMath.src/M000018.html +1 -1
  26. data/doc/classes/LongMath.src/M000019.html +1 -1
  27. data/doc/classes/LongMath.src/M000020.html +1 -1
  28. data/doc/classes/LongMath.src/M000021.html +1 -1
  29. data/doc/classes/LongMath.src/M000022.html +1 -1
  30. data/doc/classes/LongMath.src/M000023.html +1 -1
  31. data/doc/classes/LongMath.src/M000024.html +1 -1
  32. data/doc/classes/LongMath.src/M000025.html +1 -1
  33. data/doc/classes/LongMath/LongDecimal.html +2 -2
  34. data/doc/classes/LongMath/LongDecimal.src/M000060.html +1 -1
  35. data/doc/classes/LongMath/LongDecimal.src/M000061.html +1 -1
  36. data/doc/classes/LongMath/LongDecimal.src/M000062.html +1 -1
  37. data/doc/classes/LongMath/LongDecimal.src/M000063.html +1 -1
  38. data/doc/classes/LongMath/LongDecimal.src/M000064.html +1 -1
  39. data/doc/classes/LongMath/LongDecimal.src/M000065.html +1 -1
  40. data/doc/classes/LongMath/LongDecimal.src/M000066.html +1 -1
  41. data/doc/classes/LongMath/LongDecimal.src/M000067.html +1 -1
  42. data/doc/classes/LongMath/LongDecimal.src/M000068.html +1 -1
  43. data/doc/classes/LongMath/LongDecimal.src/M000069.html +1 -1
  44. data/doc/classes/LongMath/LongDecimal.src/M000070.html +1 -1
  45. data/doc/classes/LongMath/LongDecimal.src/M000071.html +1 -1
  46. data/doc/classes/LongMath/LongDecimal.src/M000072.html +1 -1
  47. data/doc/classes/LongMath/LongDecimal.src/M000073.html +1 -1
  48. data/doc/classes/LongMath/LongDecimal.src/M000074.html +1 -1
  49. data/doc/classes/LongMath/LongDecimal.src/M000075.html +1 -1
  50. data/doc/classes/LongMath/LongDecimal.src/M000076.html +1 -1
  51. data/doc/classes/LongMath/LongDecimal.src/M000077.html +1 -1
  52. data/doc/classes/LongMath/LongDecimal.src/M000078.html +1 -1
  53. data/doc/classes/LongMath/LongDecimal.src/M000079.html +1 -1
  54. data/doc/classes/LongMath/LongDecimal.src/M000080.html +1 -1
  55. data/doc/classes/LongMath/LongDecimal.src/M000081.html +1 -1
  56. data/doc/classes/LongMath/LongDecimal.src/M000082.html +1 -1
  57. data/doc/classes/LongMath/LongDecimal.src/M000083.html +1 -1
  58. data/doc/classes/LongMath/LongDecimal.src/M000085.html +1 -1
  59. data/doc/classes/LongMath/LongDecimal.src/M000086.html +1 -1
  60. data/doc/classes/LongMath/LongDecimal.src/M000087.html +1 -1
  61. data/doc/classes/LongMath/LongDecimal.src/M000088.html +1 -1
  62. data/doc/classes/LongMath/LongDecimal.src/M000089.html +1 -1
  63. data/doc/classes/LongMath/LongDecimal.src/M000090.html +1 -1
  64. data/doc/classes/LongMath/LongDecimal.src/M000091.html +1 -1
  65. data/doc/classes/LongMath/LongDecimal.src/M000092.html +1 -1
  66. data/doc/classes/LongMath/LongDecimal.src/M000093.html +1 -1
  67. data/doc/classes/LongMath/LongDecimal.src/M000094.html +1 -1
  68. data/doc/classes/LongMath/LongDecimal.src/M000095.html +1 -1
  69. data/doc/classes/LongMath/LongDecimal.src/M000096.html +1 -1
  70. data/doc/classes/LongMath/LongDecimal.src/M000097.html +1 -1
  71. data/doc/classes/LongMath/LongDecimal.src/M000098.html +1 -1
  72. data/doc/classes/LongMath/LongDecimal.src/M000099.html +1 -1
  73. data/doc/classes/LongMath/LongDecimal.src/M000100.html +1 -1
  74. data/doc/classes/LongMath/LongDecimal.src/M000101.html +1 -1
  75. data/doc/classes/LongMath/LongDecimal.src/M000102.html +1 -1
  76. data/doc/classes/LongMath/LongDecimal.src/M000103.html +1 -1
  77. data/doc/classes/LongMath/LongDecimal.src/M000104.html +1 -1
  78. data/doc/classes/LongMath/LongDecimal.src/M000105.html +1 -1
  79. data/doc/classes/LongMath/LongDecimal.src/M000106.html +1 -1
  80. data/doc/classes/LongMath/LongDecimal.src/M000107.html +1 -1
  81. data/doc/classes/LongMath/LongDecimal.src/M000108.html +1 -1
  82. data/doc/classes/LongMath/LongDecimal.src/M000109.html +1 -1
  83. data/doc/classes/LongMath/LongDecimal.src/M000110.html +1 -1
  84. data/doc/classes/LongMath/LongDecimal.src/M000111.html +1 -1
  85. data/doc/classes/LongMath/LongDecimal.src/M000112.html +1 -1
  86. data/doc/classes/LongMath/LongDecimal.src/M000113.html +1 -1
  87. data/doc/classes/LongMath/LongDecimal.src/M000114.html +1 -1
  88. data/doc/classes/LongMath/LongDecimal.src/M000115.html +1 -1
  89. data/doc/classes/LongMath/LongDecimal.src/M000116.html +1 -1
  90. data/doc/classes/LongMath/LongDecimal.src/M000117.html +1 -1
  91. data/doc/classes/LongMath/LongDecimal.src/M000119.html +1 -1
  92. data/doc/classes/LongMath/LongDecimal.src/M000121.html +1 -1
  93. data/doc/classes/LongMath/LongDecimal.src/M000122.html +1 -1
  94. data/doc/classes/LongMath/LongDecimal.src/M000123.html +1 -1
  95. data/doc/classes/LongMath/LongDecimal.src/M000124.html +1 -1
  96. data/doc/classes/LongMath/LongDecimal.src/M000125.html +1 -1
  97. data/doc/classes/LongMath/LongDecimal.src/M000126.html +1 -1
  98. data/doc/classes/LongMath/LongDecimal.src/M000129.html +1 -1
  99. data/doc/classes/LongMath/LongDecimal.src/M000130.html +1 -1
  100. data/doc/classes/LongMath/LongDecimal.src/M000131.html +1 -1
  101. data/doc/classes/LongMath/LongDecimal.src/M000132.html +1 -1
  102. data/doc/classes/LongMath/LongDecimal.src/M000133.html +1 -1
  103. data/doc/classes/LongMath/LongDecimalQuot.html +2 -2
  104. data/doc/classes/LongMath/LongDecimalQuot.src/M000026.html +1 -1
  105. data/doc/classes/LongMath/LongDecimalQuot.src/M000027.html +1 -1
  106. data/doc/classes/LongMath/LongDecimalQuot.src/M000028.html +1 -1
  107. data/doc/classes/LongMath/LongDecimalQuot.src/M000029.html +1 -1
  108. data/doc/classes/LongMath/LongDecimalQuot.src/M000030.html +1 -1
  109. data/doc/classes/LongMath/LongDecimalQuot.src/M000031.html +1 -1
  110. data/doc/classes/LongMath/LongDecimalQuot.src/M000032.html +1 -1
  111. data/doc/classes/LongMath/LongDecimalQuot.src/M000033.html +1 -1
  112. data/doc/classes/LongMath/LongDecimalQuot.src/M000034.html +1 -1
  113. data/doc/classes/LongMath/LongDecimalQuot.src/M000035.html +1 -1
  114. data/doc/classes/LongMath/LongDecimalQuot.src/M000036.html +1 -1
  115. data/doc/classes/LongMath/LongDecimalQuot.src/M000037.html +1 -1
  116. data/doc/classes/LongMath/LongDecimalQuot.src/M000038.html +1 -1
  117. data/doc/classes/LongMath/LongDecimalQuot.src/M000039.html +1 -1
  118. data/doc/classes/LongMath/LongDecimalQuot.src/M000040.html +1 -1
  119. data/doc/classes/LongMath/LongDecimalQuot.src/M000041.html +1 -1
  120. data/doc/classes/LongMath/LongDecimalQuot.src/M000042.html +1 -1
  121. data/doc/classes/LongMath/LongDecimalQuot.src/M000043.html +1 -1
  122. data/doc/classes/LongMath/LongDecimalQuot.src/M000044.html +1 -1
  123. data/doc/classes/LongMath/LongDecimalQuot.src/M000045.html +1 -1
  124. data/doc/classes/LongMath/LongDecimalQuot.src/M000046.html +1 -1
  125. data/doc/classes/LongMath/LongDecimalQuot.src/M000047.html +1 -1
  126. data/doc/classes/LongMath/LongDecimalQuot.src/M000048.html +1 -1
  127. data/doc/classes/LongMath/LongDecimalQuot.src/M000049.html +1 -1
  128. data/doc/classes/LongMath/LongDecimalQuot.src/M000050.html +1 -1
  129. data/doc/classes/LongMath/LongDecimalQuot.src/M000051.html +1 -1
  130. data/doc/classes/LongMath/LongDecimalQuot.src/M000052.html +1 -1
  131. data/doc/classes/LongMath/LongDecimalQuot.src/M000053.html +1 -1
  132. data/doc/classes/LongMath/LongDecimalQuot.src/M000054.html +1 -1
  133. data/doc/classes/LongMath/LongDecimalQuot.src/M000055.html +1 -1
  134. data/doc/classes/LongMath/LongDecimalQuot.src/M000058.html +1 -1
  135. data/doc/classes/LongMath/LongDecimalQuot.src/M000059.html +1 -1
  136. data/doc/classes/LongMath/Numeric.html +2 -2
  137. data/doc/classes/LongMath/Numeric.src/M000134.html +1 -1
  138. data/doc/created.rid +1 -1
  139. data/doc/dot/f_0.dot +1 -1
  140. data/doc/dot/f_0.png +0 -0
  141. data/doc/files/lib/{longdecimal_rb.html → long-decimal_rb.html} +7 -7
  142. data/doc/fr_file_index.html +1 -1
  143. data/doc/index.html +1 -1
  144. data/install.rb +1 -1
  145. data/lib/long-decimal.rb +2246 -0
  146. data/lib/longdecimal.rb +1 -1
  147. data/make_doc.rb +1 -1
  148. data/test/testlongdecimal.rb +6 -6
  149. data/version.rb +1 -1
  150. metadata +3 -149
  151. data/doc/classes/LongDecimal.html +0 -1432
  152. data/doc/classes/LongDecimal.src/M000040.html +0 -18
  153. data/doc/classes/LongDecimal.src/M000041.html +0 -18
  154. data/doc/classes/LongDecimal.src/M000042.html +0 -18
  155. data/doc/classes/LongDecimal.src/M000043.html +0 -18
  156. data/doc/classes/LongDecimal.src/M000044.html +0 -18
  157. data/doc/classes/LongDecimal.src/M000045.html +0 -18
  158. data/doc/classes/LongDecimal.src/M000046.html +0 -20
  159. data/doc/classes/LongDecimal.src/M000047.html +0 -109
  160. data/doc/classes/LongDecimal.src/M000048.html +0 -18
  161. data/doc/classes/LongDecimal.src/M000049.html +0 -18
  162. data/doc/classes/LongDecimal.src/M000050.html +0 -34
  163. data/doc/classes/LongDecimal.src/M000051.html +0 -41
  164. data/doc/classes/LongDecimal.src/M000052.html +0 -35
  165. data/doc/classes/LongDecimal.src/M000053.html +0 -18
  166. data/doc/classes/LongDecimal.src/M000054.html +0 -29
  167. data/doc/classes/LongDecimal.src/M000055.html +0 -18
  168. data/doc/classes/LongDecimal.src/M000056.html +0 -22
  169. data/doc/classes/LongDecimal.src/M000057.html +0 -18
  170. data/doc/classes/LongDecimal.src/M000058.html +0 -18
  171. data/doc/classes/LongDecimal.src/M000059.html +0 -20
  172. data/doc/classes/LongDecimal.src/M000060.html +0 -18
  173. data/doc/classes/LongDecimal.src/M000062.html +0 -29
  174. data/doc/classes/LongDecimal.src/M000063.html +0 -27
  175. data/doc/classes/LongDecimal.src/M000064.html +0 -18
  176. data/doc/classes/LongDecimal.src/M000066.html +0 -18
  177. data/doc/classes/LongDecimal.src/M000067.html +0 -18
  178. data/doc/classes/LongDecimal.src/M000068.html +0 -18
  179. data/doc/classes/LongDecimal.src/M000069.html +0 -18
  180. data/doc/classes/LongDecimal.src/M000070.html +0 -18
  181. data/doc/classes/LongDecimal.src/M000071.html +0 -22
  182. data/doc/classes/LongDecimal.src/M000072.html +0 -23
  183. data/doc/classes/LongDecimal.src/M000073.html +0 -23
  184. data/doc/classes/LongDecimal.src/M000074.html +0 -23
  185. data/doc/classes/LongDecimal.src/M000075.html +0 -18
  186. data/doc/classes/LongDecimal.src/M000076.html +0 -29
  187. data/doc/classes/LongDecimal.src/M000077.html +0 -23
  188. data/doc/classes/LongDecimal.src/M000078.html +0 -23
  189. data/doc/classes/LongDecimal.src/M000079.html +0 -34
  190. data/doc/classes/LongDecimal.src/M000080.html +0 -22
  191. data/doc/classes/LongDecimal.src/M000081.html +0 -19
  192. data/doc/classes/LongDecimal.src/M000082.html +0 -23
  193. data/doc/classes/LongDecimal.src/M000083.html +0 -23
  194. data/doc/classes/LongDecimal.src/M000084.html +0 -23
  195. data/doc/classes/LongDecimal.src/M000085.html +0 -18
  196. data/doc/classes/LongDecimal.src/M000086.html +0 -21
  197. data/doc/classes/LongDecimal.src/M000087.html +0 -21
  198. data/doc/classes/LongDecimal.src/M000088.html +0 -18
  199. data/doc/classes/LongDecimal.src/M000089.html +0 -18
  200. data/doc/classes/LongDecimal.src/M000090.html +0 -23
  201. data/doc/classes/LongDecimal.src/M000091.html +0 -23
  202. data/doc/classes/LongDecimal.src/M000092.html +0 -19
  203. data/doc/classes/LongDecimal.src/M000093.html +0 -23
  204. data/doc/classes/LongDecimal.src/M000094.html +0 -18
  205. data/doc/classes/LongDecimal.src/M000095.html +0 -30
  206. data/doc/classes/LongDecimal.src/M000096.html +0 -18
  207. data/doc/classes/LongDecimal.src/M000097.html +0 -18
  208. data/doc/classes/LongDecimal.src/M000098.html +0 -18
  209. data/doc/classes/LongDecimal.src/M000099.html +0 -23
  210. data/doc/classes/LongDecimal.src/M000100.html +0 -19
  211. data/doc/classes/LongDecimal.src/M000101.html +0 -18
  212. data/doc/classes/LongDecimal.src/M000102.html +0 -45
  213. data/doc/classes/LongDecimal.src/M000103.html +0 -18
  214. data/doc/classes/LongDecimal.src/M000104.html +0 -18
  215. data/doc/classes/LongDecimal.src/M000107.html +0 -18
  216. data/doc/classes/LongDecimal.src/M000108.html +0 -18
  217. data/doc/classes/LongDecimal.src/M000109.html +0 -18
  218. data/doc/classes/LongDecimal.src/M000110.html +0 -18
  219. data/doc/classes/LongDecimalQuot.html +0 -757
  220. data/doc/classes/LongDecimalQuot.src/M000003.html +0 -18
  221. data/doc/classes/LongDecimalQuot.src/M000004.html +0 -28
  222. data/doc/classes/LongDecimalQuot.src/M000005.html +0 -18
  223. data/doc/classes/LongDecimalQuot.src/M000006.html +0 -18
  224. data/doc/classes/LongDecimalQuot.src/M000007.html +0 -18
  225. data/doc/classes/LongDecimalQuot.src/M000008.html +0 -18
  226. data/doc/classes/LongDecimalQuot.src/M000009.html +0 -19
  227. data/doc/classes/LongDecimalQuot.src/M000010.html +0 -18
  228. data/doc/classes/LongDecimalQuot.src/M000011.html +0 -18
  229. data/doc/classes/LongDecimalQuot.src/M000012.html +0 -18
  230. data/doc/classes/LongDecimalQuot.src/M000013.html +0 -18
  231. data/doc/classes/LongDecimalQuot.src/M000014.html +0 -18
  232. data/doc/classes/LongDecimalQuot.src/M000015.html +0 -22
  233. data/doc/classes/LongDecimalQuot.src/M000016.html +0 -23
  234. data/doc/classes/LongDecimalQuot.src/M000017.html +0 -23
  235. data/doc/classes/LongDecimalQuot.src/M000018.html +0 -23
  236. data/doc/classes/LongDecimalQuot.src/M000019.html +0 -23
  237. data/doc/classes/LongDecimalQuot.src/M000020.html +0 -35
  238. data/doc/classes/LongDecimalQuot.src/M000021.html +0 -22
  239. data/doc/classes/LongDecimalQuot.src/M000022.html +0 -19
  240. data/doc/classes/LongDecimalQuot.src/M000023.html +0 -18
  241. data/doc/classes/LongDecimalQuot.src/M000024.html +0 -18
  242. data/doc/classes/LongDecimalQuot.src/M000025.html +0 -18
  243. data/doc/classes/LongDecimalQuot.src/M000026.html +0 -18
  244. data/doc/classes/LongDecimalQuot.src/M000027.html +0 -79
  245. data/doc/classes/LongDecimalQuot.src/M000028.html +0 -36
  246. data/doc/classes/LongDecimalQuot.src/M000029.html +0 -18
  247. data/doc/classes/LongDecimalQuot.src/M000030.html +0 -23
  248. data/doc/classes/LongDecimalQuot.src/M000031.html +0 -19
  249. data/doc/classes/LongDecimalQuot.src/M000032.html +0 -18
  250. data/doc/classes/LongDecimalQuot.src/M000033.html +0 -18
  251. data/doc/classes/LongDecimalQuot.src/M000034.html +0 -18
  252. data/doc/classes/LongDecimalQuot.src/M000037.html +0 -18
  253. data/doc/classes/LongDecimalQuot.src/M000038.html +0 -18
  254. data/doc/classes/LongDecimalQuot.src/M000039.html +0 -18
  255. data/doc/classes/LongDecimalRoundingMode/RoundingModeClass.src/M000122.html +0 -22
  256. data/doc/classes/LongDecimalRoundingMode/RoundingModeClass.src/M000128.html +0 -22
  257. data/doc/classes/LongDecimalRoundingMode/RoundingModeClass.src/M000133.html +0 -22
  258. data/doc/classes/LongDecimalRoundingMode/RoundingModeClass.src/M000136.html +0 -22
  259. data/doc/classes/LongMath.src/M000112.html +0 -19
  260. data/doc/classes/LongMath.src/M000113.html +0 -18
  261. data/doc/classes/LongMath.src/M000114.html +0 -18
  262. data/doc/classes/LongMath.src/M000115.html +0 -19
  263. data/doc/classes/LongMath.src/M000116.html +0 -18
  264. data/doc/classes/LongMath.src/M000117.html +0 -32
  265. data/doc/classes/LongMath.src/M000118.html +0 -32
  266. data/doc/classes/LongMath.src/M000119.html +0 -19
  267. data/doc/classes/LongMath.src/M000120.html +0 -43
  268. data/doc/classes/LongMath.src/M000121.html +0 -19
  269. data/doc/classes/LongMath.src/M000122.html +0 -73
  270. data/doc/classes/LongMath.src/M000123.html +0 -35
  271. data/doc/classes/LongMath.src/M000124.html +0 -50
  272. data/doc/classes/LongMath.src/M000125.html +0 -47
  273. data/doc/classes/LongMath.src/M000126.html +0 -21
  274. data/doc/classes/LongMath.src/M000127.html +0 -108
  275. data/doc/classes/LongMath/LongDecimal.src/M000058.html +0 -18
  276. data/doc/classes/LongMath/LongDecimal.src/M000059.html +0 -18
  277. data/doc/classes/LongMath/LongDecimal.src/M000084.html +0 -18
  278. data/doc/classes/LongMath/LongDecimal.src/M000118.html +0 -30
  279. data/doc/classes/LongMath/LongDecimal.src/M000120.html +0 -19
  280. data/doc/classes/LongMath/LongDecimal.src/M000127.html +0 -19
  281. data/doc/classes/LongMath/LongDecimal.src/M000128.html +0 -18
  282. data/doc/classes/LongMath/LongDecimal.src/M000134.html +0 -18
  283. data/doc/classes/LongMath/LongDecimalQuot.src/M000024.html +0 -18
  284. data/doc/classes/LongMath/LongDecimalQuot.src/M000025.html +0 -28
  285. data/doc/classes/LongMath/LongDecimalQuot.src/M000056.html +0 -18
  286. data/doc/classes/LongMath/LongDecimalQuot.src/M000057.html +0 -18
  287. data/doc/classes/LongMath/LongDecimalQuot.src/M000060.html +0 -18
  288. data/doc/classes/LongMath/Numeric.src/M000132.html +0 -18
  289. data/doc/classes/LongMath/Numeric.src/M000135.html +0 -18
  290. data/doc/classes/Numeric.html +0 -149
  291. data/doc/classes/Numeric.src/M000111.html +0 -18
  292. data/doc/files/lib/longdecimal_rb.src/M000001.html +0 -22
  293. data/doc/files/lib/longdecimal_rb.src/M000002.html +0 -18
@@ -10,7 +10,7 @@
10
10
  <link rel="stylesheet" href="../../.././rdoc-style.css" type="text/css" media="screen" />
11
11
  </head>
12
12
  <body class="standalone-code">
13
- <pre><span class="ruby-comment cmt"># File lib/longdecimal.rb, line 2027</span>
13
+ <pre><span class="ruby-comment cmt"># File lib/long-decimal.rb, line 2027</span>
14
14
  <span class="ruby-keyword kw">def</span> <span class="ruby-identifier">reciprocal</span>
15
15
  <span class="ruby-value">1</span> <span class="ruby-operator">/</span> <span class="ruby-keyword kw">self</span>
16
16
  <span class="ruby-keyword kw">end</span></pre>
@@ -10,7 +10,7 @@
10
10
  <link rel="stylesheet" href="../../.././rdoc-style.css" type="text/css" media="screen" />
11
11
  </head>
12
12
  <body class="standalone-code">
13
- <pre><span class="ruby-comment cmt"># File lib/longdecimal.rb, line 2034</span>
13
+ <pre><span class="ruby-comment cmt"># File lib/long-decimal.rb, line 2034</span>
14
14
  <span class="ruby-keyword kw">def</span> <span class="ruby-identifier">abs</span>
15
15
  <span class="ruby-constant">LongDecimalQuot</span>(<span class="ruby-identifier">rat</span>.<span class="ruby-identifier">abs</span>, <span class="ruby-identifier">scale</span>)
16
16
  <span class="ruby-keyword kw">end</span></pre>
@@ -10,7 +10,7 @@
10
10
  <link rel="stylesheet" href="../../.././rdoc-style.css" type="text/css" media="screen" />
11
11
  </head>
12
12
  <body class="standalone-code">
13
- <pre><span class="ruby-comment cmt"># File lib/longdecimal.rb, line 2038</span>
13
+ <pre><span class="ruby-comment cmt"># File lib/long-decimal.rb, line 2038</span>
14
14
  <span class="ruby-keyword kw">def</span> <span class="ruby-identifier">abs2</span>
15
15
  <span class="ruby-keyword kw">self</span>.<span class="ruby-identifier">abs</span>.<span class="ruby-identifier">square</span>
16
16
  <span class="ruby-keyword kw">end</span></pre>
@@ -10,7 +10,7 @@
10
10
  <link rel="stylesheet" href="../../.././rdoc-style.css" type="text/css" media="screen" />
11
11
  </head>
12
12
  <body class="standalone-code">
13
- <pre><span class="ruby-comment cmt"># File lib/longdecimal.rb, line 2046</span>
13
+ <pre><span class="ruby-comment cmt"># File lib/long-decimal.rb, line 2046</span>
14
14
  <span class="ruby-keyword kw">def</span> <span class="ruby-identifier">round_to_scale</span>(<span class="ruby-identifier">new_scale</span> = <span class="ruby-ivar">@scale</span>, <span class="ruby-identifier">mode</span> = <span class="ruby-constant">ROUND_UNNECESSARY</span>)
15
15
 
16
16
  <span class="ruby-identifier">raise</span> <span class="ruby-constant">TypeError</span>, <span class="ruby-node">&quot;new_scale #{new_scale.inspect} must be integer&quot;</span> <span class="ruby-keyword kw">unless</span> <span class="ruby-identifier">new_scale</span>.<span class="ruby-identifier">kind_of?</span> <span class="ruby-constant">Integer</span>
@@ -10,7 +10,7 @@
10
10
  <link rel="stylesheet" href="../../.././rdoc-style.css" type="text/css" media="screen" />
11
11
  </head>
12
12
  <body class="standalone-code">
13
- <pre><span class="ruby-comment cmt"># File lib/longdecimal.rb, line 2118</span>
13
+ <pre><span class="ruby-comment cmt"># File lib/long-decimal.rb, line 2118</span>
14
14
  <span class="ruby-keyword kw">def</span> <span class="ruby-identifier">coerce</span>(<span class="ruby-identifier">other</span>)
15
15
  <span class="ruby-keyword kw">if</span> <span class="ruby-identifier">other</span>.<span class="ruby-identifier">kind_of?</span> <span class="ruby-constant">LongDecimal</span> <span class="ruby-keyword kw">then</span>
16
16
  <span class="ruby-keyword kw">return</span> <span class="ruby-constant">LongDecimalQuot</span>(<span class="ruby-identifier">other</span>.<span class="ruby-identifier">to_r</span>, <span class="ruby-identifier">other</span>.<span class="ruby-identifier">scale</span>), <span class="ruby-keyword kw">self</span>
@@ -10,7 +10,7 @@
10
10
  <link rel="stylesheet" href="../../.././rdoc-style.css" type="text/css" media="screen" />
11
11
  </head>
12
12
  <body class="standalone-code">
13
- <pre><span class="ruby-comment cmt"># File lib/longdecimal.rb, line 2150</span>
13
+ <pre><span class="ruby-comment cmt"># File lib/long-decimal.rb, line 2150</span>
14
14
  <span class="ruby-keyword kw">def</span> <span class="ruby-operator">==</span>(<span class="ruby-identifier">other</span>)
15
15
  (<span class="ruby-identifier">other</span>.<span class="ruby-identifier">kind_of?</span> <span class="ruby-constant">LongDecimalQuot</span>) <span class="ruby-operator">&amp;&amp;</span> (<span class="ruby-keyword kw">self</span> <span class="ruby-operator">&lt;=&gt;</span> <span class="ruby-identifier">other</span>) <span class="ruby-operator">==</span> <span class="ruby-value">0</span> <span class="ruby-operator">&amp;&amp;</span> <span class="ruby-keyword kw">self</span>.<span class="ruby-identifier">scale</span> <span class="ruby-operator">==</span> <span class="ruby-identifier">other</span>.<span class="ruby-identifier">scale</span>
16
16
  <span class="ruby-keyword kw">end</span></pre>
@@ -10,7 +10,7 @@
10
10
  <link rel="stylesheet" href="../../.././rdoc-style.css" type="text/css" media="screen" />
11
11
  </head>
12
12
  <body class="standalone-code">
13
- <pre><span class="ruby-comment cmt"># File lib/longdecimal.rb, line 2157</span>
13
+ <pre><span class="ruby-comment cmt"># File lib/long-decimal.rb, line 2157</span>
14
14
  <span class="ruby-keyword kw">def</span> <span class="ruby-operator">&lt;=&gt;</span> (<span class="ruby-identifier">other</span>)
15
15
  <span class="ruby-identifier">diff</span> = (<span class="ruby-keyword kw">self</span> <span class="ruby-operator">-</span> <span class="ruby-identifier">other</span>)
16
16
  <span class="ruby-keyword kw">if</span> (<span class="ruby-identifier">diff</span>.<span class="ruby-identifier">kind_of?</span> <span class="ruby-constant">LongDecimal</span>) <span class="ruby-operator">||</span> (<span class="ruby-identifier">diff</span>.<span class="ruby-identifier">kind_of?</span> <span class="ruby-constant">LongDecimalQuot</span>) <span class="ruby-keyword kw">then</span>
@@ -10,7 +10,7 @@
10
10
  <link rel="stylesheet" href="../../.././rdoc-style.css" type="text/css" media="screen" />
11
11
  </head>
12
12
  <body class="standalone-code">
13
- <pre><span class="ruby-comment cmt"># File lib/longdecimal.rb, line 2169</span>
13
+ <pre><span class="ruby-comment cmt"># File lib/long-decimal.rb, line 2169</span>
14
14
  <span class="ruby-keyword kw">def</span> <span class="ruby-identifier">scale_ufo</span>(<span class="ruby-identifier">other</span>)
15
15
  <span class="ruby-identifier">raise</span> <span class="ruby-constant">TypeError</span>, <span class="ruby-value str">&quot;only works for LongDecimal and LongDecimalQuot&quot;</span> <span class="ruby-keyword kw">unless</span> (<span class="ruby-identifier">other</span>.<span class="ruby-identifier">kind_of?</span> <span class="ruby-constant">LongDecimal</span>) <span class="ruby-operator">||</span> (<span class="ruby-identifier">other</span>.<span class="ruby-identifier">kind_of?</span> <span class="ruby-constant">LongDecimalQuot</span>)
16
16
  <span class="ruby-keyword kw">self</span>.<span class="ruby-identifier">scale</span> <span class="ruby-operator">&lt;=&gt;</span> <span class="ruby-identifier">other</span>.<span class="ruby-identifier">scale</span>
@@ -10,7 +10,7 @@
10
10
  <link rel="stylesheet" href="../../.././rdoc-style.css" type="text/css" media="screen" />
11
11
  </head>
12
12
  <body class="standalone-code">
13
- <pre><span class="ruby-comment cmt"># File lib/longdecimal.rb, line 2177</span>
13
+ <pre><span class="ruby-comment cmt"># File lib/long-decimal.rb, line 2177</span>
14
14
  <span class="ruby-keyword kw">def</span> <span class="ruby-identifier">scale_equal</span>(<span class="ruby-identifier">other</span>)
15
15
  <span class="ruby-identifier">scale_ufo</span>(<span class="ruby-identifier">other</span>).<span class="ruby-identifier">zero?</span>
16
16
  <span class="ruby-keyword kw">end</span></pre>
@@ -10,7 +10,7 @@
10
10
  <link rel="stylesheet" href="../../.././rdoc-style.css" type="text/css" media="screen" />
11
11
  </head>
12
12
  <body class="standalone-code">
13
- <pre><span class="ruby-comment cmt"># File lib/longdecimal.rb, line 2184</span>
13
+ <pre><span class="ruby-comment cmt"># File lib/long-decimal.rb, line 2184</span>
14
14
  <span class="ruby-keyword kw">def</span> <span class="ruby-identifier">is_int?</span>
15
15
  <span class="ruby-identifier">denominator</span> <span class="ruby-operator">==</span> <span class="ruby-value">1</span>
16
16
  <span class="ruby-keyword kw">end</span></pre>
@@ -10,7 +10,7 @@
10
10
  <link rel="stylesheet" href="../../.././rdoc-style.css" type="text/css" media="screen" />
11
11
  </head>
12
12
  <body class="standalone-code">
13
- <pre><span class="ruby-comment cmt"># File lib/longdecimal.rb, line 2191</span>
13
+ <pre><span class="ruby-comment cmt"># File lib/long-decimal.rb, line 2191</span>
14
14
  <span class="ruby-keyword kw">def</span> <span class="ruby-identifier">sgn</span>
15
15
  <span class="ruby-identifier">numerator</span> <span class="ruby-operator">&lt;=&gt;</span> <span class="ruby-value">0</span>
16
16
  <span class="ruby-keyword kw">end</span></pre>
@@ -10,7 +10,7 @@
10
10
  <link rel="stylesheet" href="../../.././rdoc-style.css" type="text/css" media="screen" />
11
11
  </head>
12
12
  <body class="standalone-code">
13
- <pre><span class="ruby-comment cmt"># File lib/longdecimal.rb, line 2200</span>
13
+ <pre><span class="ruby-comment cmt"># File lib/long-decimal.rb, line 2200</span>
14
14
  <span class="ruby-keyword kw">def</span> <span class="ruby-identifier">hash</span>
15
15
  <span class="ruby-identifier">rat</span>.<span class="ruby-identifier">hash</span> <span class="ruby-operator">^</span> <span class="ruby-identifier">scale</span>.<span class="ruby-identifier">hash</span>
16
16
  <span class="ruby-keyword kw">end</span></pre>
@@ -10,7 +10,7 @@
10
10
  <link rel="stylesheet" href="../../.././rdoc-style.css" type="text/css" media="screen" />
11
11
  </head>
12
12
  <body class="standalone-code">
13
- <pre><span class="ruby-comment cmt"># File lib/longdecimal.rb, line 2208</span>
13
+ <pre><span class="ruby-comment cmt"># File lib/long-decimal.rb, line 2208</span>
14
14
  <span class="ruby-keyword kw">def</span> <span class="ruby-identifier">inspect</span>
15
15
  <span class="ruby-identifier">sprintf</span>(<span class="ruby-value str">&quot;LongDecimalQuot(Rational(%s, %s), %s)&quot;</span>, <span class="ruby-identifier">numerator</span>.<span class="ruby-identifier">inspect</span>, <span class="ruby-identifier">denominator</span>.<span class="ruby-identifier">inspect</span>, <span class="ruby-identifier">scale</span>.<span class="ruby-identifier">inspect</span>)
16
16
  <span class="ruby-keyword kw">end</span></pre>
@@ -55,8 +55,8 @@
55
55
  <tr class="top-aligned-row">
56
56
  <td><strong>In:</strong></td>
57
57
  <td>
58
- <a href="../../files/lib/longdecimal_rb.html">
59
- lib/longdecimal.rb
58
+ <a href="../../files/lib/long-decimal_rb.html">
59
+ lib/long-decimal.rb
60
60
  </a>
61
61
  <br />
62
62
  </td>
@@ -10,7 +10,7 @@
10
10
  <link rel="stylesheet" href="../../.././rdoc-style.css" type="text/css" media="screen" />
11
11
  </head>
12
12
  <body class="standalone-code">
13
- <pre><span class="ruby-comment cmt"># File lib/longdecimal.rb, line 2240</span>
13
+ <pre><span class="ruby-comment cmt"># File lib/long-decimal.rb, line 2240</span>
14
14
  <span class="ruby-keyword kw">def</span> <span class="ruby-identifier">to_ld</span>
15
15
  <span class="ruby-constant">LongDecimal</span>(<span class="ruby-keyword kw">self</span>)
16
16
  <span class="ruby-keyword kw">end</span></pre>
data/doc/created.rid CHANGED
@@ -1 +1 @@
1
- Sat Mar 18 07:40:45 CET 2006
1
+ Sat Mar 18 10:59:14 CET 2006
data/doc/dot/f_0.dot CHANGED
@@ -3,7 +3,7 @@ digraph TopLevel {
3
3
  bgcolor = lightcyan1
4
4
  fontname = Arial
5
5
  fontsize = 8
6
- label = "lib/longdecimal.rb"
6
+ label = "lib/long-decimal.rb"
7
7
  node [
8
8
  fontname = Arial,
9
9
  fontsize = 8,
data/doc/dot/f_0.png CHANGED
Binary file
@@ -5,7 +5,7 @@
5
5
 
6
6
  <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
7
7
  <head>
8
- <title>File: longdecimal.rb</title>
8
+ <title>File: long-decimal.rb</title>
9
9
  <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
10
10
  <meta http-equiv="Content-Script-Type" content="text/javascript" />
11
11
  <link rel="stylesheet" href="../.././rdoc-style.css" type="text/css" media="screen" />
@@ -47,16 +47,16 @@
47
47
 
48
48
 
49
49
  <div id="fileHeader">
50
- <h1>longdecimal.rb</h1>
50
+ <h1>long-decimal.rb</h1>
51
51
  <table class="header-table">
52
52
  <tr class="top-aligned-row">
53
53
  <td><strong>Path:</strong></td>
54
- <td>lib/longdecimal.rb
54
+ <td>lib/long-decimal.rb
55
55
  </td>
56
56
  </tr>
57
57
  <tr class="top-aligned-row">
58
58
  <td><strong>Last Update:</strong></td>
59
- <td>Sat Mar 18 07:40:05 CET 2006</td>
59
+ <td>Sat Mar 18 09:34:28 CET 2006</td>
60
60
  </tr>
61
61
  </table>
62
62
  </div>
@@ -82,12 +82,12 @@
82
82
 
83
83
  <div id="description">
84
84
  <p>
85
- longdecimal.rb &#8212; Arbitrary precision decimals with fixed decimal
85
+ long-decimal.rb &#8212; Arbitrary precision decimals with fixed decimal
86
86
  point
87
87
  </p>
88
88
  <p>
89
- CVS-ID: $Header: /var/cvs/long-decimal/long-decimal/lib/longdecimal.rb,v
90
- 1.9 2006/03/18 06:03:58 bk1 Exp $ CVS-Label: $Name: PRE_ALPHA_0_12 $
89
+ CVS-ID: $Header: /var/cvs/long-decimal/long-decimal/lib/long-decimal.rb,v
90
+ 1.1 2006/03/18 08:34:28 bk1 Exp $ CVS-Label: $Name: PRE_ALPHA_0_13 $
91
91
  Author: $Author: bk1 $ (Karl Brodowsky)
92
92
  </p>
93
93
 
@@ -20,7 +20,7 @@
20
20
  <div id="index">
21
21
  <h1 class="section-bar">Files</h1>
22
22
  <div id="index-entries">
23
- <a href="files/lib/longdecimal_rb.html">lib/longdecimal.rb</a><br />
23
+ <a href="files/lib/long-decimal_rb.html">lib/long-decimal.rb</a><br />
24
24
  </div>
25
25
  </div>
26
26
  </body>
data/doc/index.html CHANGED
@@ -19,6 +19,6 @@
19
19
  <frame src="fr_class_index.html" name="Classes" />
20
20
  <frame src="fr_method_index.html" name="Methods" />
21
21
  </frameset>
22
- <frame src="files/lib/longdecimal_rb.html" name="docwin" />
22
+ <frame src="files/lib/long-decimal_rb.html" name="docwin" />
23
23
  </frameset>
24
24
  </html>
data/install.rb CHANGED
@@ -6,7 +6,7 @@ include FileUtils::Verbose
6
6
 
7
7
  include Config
8
8
 
9
- file = 'lib/longdecimal.rb'
9
+ file = 'lib/long-decimal.rb'
10
10
  dest = CONFIG["sitelibdir"]
11
11
  install(file, dest)
12
12
  # vim: set et sw=4 ts=4:
@@ -0,0 +1,2246 @@
1
+ #
2
+ # long-decimal.rb -- Arbitrary precision decimals with fixed decimal point
3
+ #
4
+ # CVS-ID: $Header: /var/cvs/long-decimal/long-decimal/lib/long-decimal.rb,v 1.1 2006/03/18 08:34:28 bk1 Exp $
5
+ # CVS-Label: $Name: PRE_ALPHA_0_13 $
6
+ # Author: $Author: bk1 $ (Karl Brodowsky)
7
+ #
8
+ require "complex"
9
+ require "rational"
10
+ require "bigdecimal"
11
+
12
+ # require "bigdecimal/math"
13
+
14
+ #
15
+ # define rounding modes to be used for LongDecimal
16
+ # this serves the purpose of an "enum" in C/C++
17
+ #
18
+ module LongDecimalRoundingMode
19
+
20
+ RoundingModeClass = Struct.new(:name, :num)
21
+
22
+ #
23
+ # enumeration class to express the possible rounding modes that are
24
+ # supported by LongDecimal
25
+ #
26
+ class RoundingModeClass
27
+ include Comparable
28
+
29
+ #
30
+ # introduce some ordering for rounding modes
31
+ #
32
+ def <=>(o)
33
+ if o.respond_to?:num
34
+ self.num <=> o.num
35
+ else
36
+ self.num <=> o
37
+ end
38
+ end
39
+ end
40
+
41
+ #
42
+ # rounding modes as constants
43
+ #
44
+ ROUND_UP = RoundingModeClass.new(:ROUND_UP, 0)
45
+ ROUND_DOWN = RoundingModeClass.new(:ROUND_DOWN, 1)
46
+ ROUND_CEILING = RoundingModeClass.new(:ROUND_CEILING, 2)
47
+ ROUND_FLOOR = RoundingModeClass.new(:ROUND_FLOOR, 3)
48
+ ROUND_HALF_UP = RoundingModeClass.new(:ROUND_HALF_UP, 4)
49
+ ROUND_HALF_DOWN = RoundingModeClass.new(:ROUND_HALF_DOWN, 5)
50
+ ROUND_HALF_EVEN = RoundingModeClass.new(:ROUND_HALF_EVEN, 6)
51
+ ROUND_UNNECESSARY = RoundingModeClass.new(:ROUND_UNNECESSARY, 7)
52
+
53
+ end # LongDecimalRoundingMode
54
+
55
+ #
56
+ # LongMath provides some helper functions to support LongDecimal and
57
+ # LongDecimalQuot, mostly operating on integers. They are used
58
+ # internally here, but possibly they can be used elsewhere as well.
59
+ # In addition LongMath provides methods like those in Math, but for
60
+ # LongDecimal instead of Float.
61
+ #
62
+ module LongMath
63
+
64
+ include LongDecimalRoundingMode
65
+
66
+ MAX_FLOATABLE = Float::MAX.to_i
67
+ MAX_EXP_ABLE = Math.log(MAX_FLOATABLE).to_i
68
+ LOG2 = Math.log(2.0)
69
+ LOG10 = Math.log(10.0)
70
+
71
+ #
72
+ # helper method for internal use: checks if word_len is a reasonable
73
+ # size for splitting a number into parts
74
+ #
75
+ def LongMath.check_word_len(word_len, name="word_len")
76
+ raise TypeError, "#{name} must be a positive number <= 1024" unless (word_len.kind_of? Fixnum) && word_len > 0 && word_len <= 1024
77
+ word_len
78
+ end
79
+
80
+ #
81
+ # helper method for internal use: checks if parameter x is an Integer
82
+ #
83
+ def LongMath.check_is_int(x, name="x")
84
+ raise TypeError, "#{name}=#{x.inspect} must be Integer" unless x.kind_of? Integer
85
+ end
86
+
87
+ #
88
+ # helper method for internal use: checks if parameter x is a LongDecimal
89
+ #
90
+ def LongMath.check_is_ld(x, name="x")
91
+ raise TypeError, "x=#{x.inspect} must be LongDecimal" unless x.kind_of? LongDecimal
92
+ end
93
+
94
+ #
95
+ # helper method for internal use: checks if parameter x is a
96
+ # reasonable value for the precision (scale) of a LongDecimal
97
+ #
98
+ def LongMath.check_is_prec(prec, name="prec")
99
+ check_is_int(prec, "prec")
100
+ raise TypeError, "#{name}=#{prec.inspect} must be >= 0" unless prec >= 0
101
+ end
102
+
103
+ #
104
+ # helper method for internal use: checks if parameter x is a
105
+ # rounding mode (instance of RoundingModeClass)
106
+ #
107
+ def LongMath.check_is_mode(mode, name="mode")
108
+ raise TypeError, "#{name}=#{mode.inspect} must be legal rounding mode" unless mode.kind_of? RoundingModeClass
109
+ end
110
+
111
+ #
112
+ # split number (Integer) x into parts of word_len bits each such
113
+ # that the concatenation of these parts as bit patterns is x
114
+ # (the opposite of merge_from_words)
115
+ #
116
+ def LongMath.split_to_words(x, word_len = 32)
117
+ check_word_len(word_len)
118
+ check_is_int(x, "x")
119
+ m = x.abs
120
+ s = (x <=> 0)
121
+ bit_pattern = (1 << word_len) - 1
122
+ words = []
123
+ while (m != 0 || words.length == 0) do
124
+ w = m & bit_pattern
125
+ m = m >> word_len
126
+ words.unshift(w)
127
+ end
128
+ if (s < 0) then
129
+ words[0] = -words[0]
130
+ end
131
+ words
132
+ end
133
+
134
+ #
135
+ # concatenate numbers given in words as bit patterns
136
+ # (the opposite of split_to_words)
137
+ #
138
+ def LongMath.merge_from_words(words, word_len = 32)
139
+ check_word_len(word_len)
140
+ raise TypeError, "words must be array of length > 0" unless (words.kind_of? Array) && words.length > 0
141
+ y = 0
142
+ s = (words[0] <=> 0)
143
+ if (s < 0) then
144
+ words[0] = -words[0]
145
+ end
146
+ words.each do |w|
147
+ y = y << word_len
148
+ y += w
149
+ end
150
+ if (s < 0) then
151
+ y = -y
152
+ end
153
+ y
154
+ end
155
+
156
+ #
157
+
158
+ # calculate the square root of an integer x using bitwise algorithm
159
+ # the result is rounded to an integer y such that
160
+ # y**2�<=�x�<�(y+1)**2
161
+ #
162
+ def LongMath.sqrtb(x)
163
+ a = sqrtb_with_remainder(x)
164
+ a[0]
165
+ end
166
+
167
+ #
168
+ #�calculate�the�an�integer�s�>=�0�and�a�remainder�r�>=�0�such�that
169
+ #�x�=�s**2�+�r�and�s**2�<=�x�<�(s+1)**2
170
+ # the bitwise algorithm is used, which works well for relatively
171
+ # small values of x.
172
+ #
173
+ def LongMath.sqrtb_with_remainder(x)
174
+ check_is_int(x, "x")
175
+
176
+ s = (x <=> 0)
177
+ if (s == 0) then
178
+ return [0, 0]
179
+ elsif (s < 0)
180
+ a = sqrtb_with_remainder(-x)
181
+ return [ Complex(0, a[0]), a[1]]
182
+ end
183
+
184
+ xwords = split_to_words(x, 2)
185
+ xi = xwords[0] - 1
186
+ yi = 1
187
+
188
+ 1.upto(xwords.length-1) do |i|
189
+ xi = (xi << 2) + xwords[i]
190
+ d0 = (yi << 2) + 1
191
+ r = xi - d0
192
+ b = 0
193
+ if (r >= 0) then
194
+ b = 1
195
+ xi = r
196
+ end
197
+ yi = (yi << 1) + b
198
+ end
199
+ return [yi, xi]
200
+ end
201
+
202
+ #
203
+
204
+ # calculate the square root of an integer using larger chunks of the
205
+ # number. The optional parameter n provides the size of these
206
+ # chunks. It is by default chosen to be 16, which is optimized for
207
+ # 32 bit systems, because internally parts of the double size are
208
+ # used.
209
+ # the result is rounded to an integer y such that
210
+ # y**2�<=�x�<�(y+1)**2
211
+ #
212
+ def LongMath.sqrtw(x, n = 16)
213
+ a = sqrtw_with_remainder(x, n)
214
+ a[0]
215
+ end
216
+
217
+ #
218
+ # calculate the an integer s >= 0 and a remainder r >= 0 such that
219
+ #�x�=�s**2�+�r�and�s**2�<=�x�<�(s+1)**2
220
+ # the wordwise algorithm is used, which works well for relatively
221
+ # large values of x. n defines the word size to be used for the
222
+ # algorithm. It is good to use half of the machine word, but the
223
+ # algorithm would also work for other values.
224
+ #
225
+ def LongMath.sqrtw_with_remainder(x, n = 16)
226
+ check_is_int(x, "x")
227
+ check_is_int(n, "n")
228
+ n2 = n<<1
229
+ n1 = n+1
230
+ check_word_len(n2, "2*n")
231
+
232
+ s = (x <=> 0)
233
+ if (s == 0) then
234
+ return [0, 0]
235
+ elsif (s < 0)
236
+ a = sqrtw_with_remainder(-x)
237
+ return [ Complex(0, a[0]), a[1]]
238
+ end
239
+
240
+ xwords = split_to_words(x, n2)
241
+ if (xwords.length == 1) then
242
+ return sqrtb_with_remainder(xwords[0])
243
+ end
244
+
245
+ # puts(xwords.inspect + "\n")
246
+ xi = (xwords[0] << n2) + xwords[1]
247
+ a = sqrtb_with_remainder(xi)
248
+ yi = a[0]
249
+ if (xwords.length <= 2) then
250
+ return a
251
+ end
252
+
253
+ xi -= yi*yi
254
+ 2.upto(xwords.length-1) do |i|
255
+ xi = (xi << n2) + xwords[i]
256
+ d0 = (yi << n1)
257
+ q = (xi / d0).to_i
258
+ q0 = q
259
+ j = 0
260
+ was_negative = false
261
+ while (true) do
262
+ d = d0 + q
263
+ r = xi - (q * d)
264
+ break if (0 <= r && (r < d || was_negative))
265
+ # puts("i=#{i} j=#{j} q=#{q} d0=#{d0} d=#{d} r=#{r} yi=#{yi} xi=#{xi}\n")
266
+ if (r < 0) then
267
+ was_negative = true
268
+ q = q-1
269
+ else
270
+ q = q+1
271
+ end
272
+ j += 1
273
+ if (j > 10) then
274
+ # puts("i=#{i} j=#{j} q=#{q} q0=#{q0} d0=#{d0} d=#{d} r=#{r} yi=#{yi} xi=#{xi}\n")
275
+ break
276
+ end
277
+ end
278
+ xi = r
279
+ yi = (yi << n) + q
280
+ end
281
+ return [ yi, xi ]
282
+ end
283
+
284
+ #
285
+
286
+ # find the gcd of an Integer x with b**n0 where n0 is a sufficiently
287
+ # high exponent
288
+ # such that gcd(x, b**m) = gcd(x, b**n) for all m, n >= n0
289
+ #
290
+ def LongMath.gcd_with_high_power(x, b)
291
+ check_is_int(x, "x")
292
+ raise ZeroDivisionError, "gcd_with_high_power of zero with \"#{b.inspect}\" would be infinity" if x.zero?
293
+ check_is_int(b, "b")
294
+ raise ZeroDivisionError, "gcd_with_high_power with b < 2 is not defined. b=\"#{b.inspect}\"" if b < 2
295
+ s = x.abs
296
+ exponent = 1
297
+ b = b.abs
298
+ if (b < s && s < MAX_FLOATABLE)
299
+ exponent = (Math.log(s) / Math.log(b)).ceil
300
+ end
301
+ power = b**exponent
302
+ result = 1
303
+ begin
304
+ f = s.gcd(power)
305
+ s /= f
306
+ result *= f
307
+ end while f > 1
308
+ result
309
+ end
310
+
311
+ #
312
+ # Find the exponent of the highest power of prime number p that divides
313
+ # the Integer x. Only works for prime numbers p (parameter prime_number).
314
+ # The caller has to make sure that p (parameter prime_number) is
315
+ # actually a prime number, because checks for primality actually cost
316
+ # something and should not be duplicated more than necessary.
317
+ # This method works even for numbers x that exceed the range of Float
318
+ #
319
+ def LongMath.multiplicity_of_factor(x, prime_number)
320
+
321
+ if (x.kind_of? Rational) || (x.kind_of? LongDecimalQuot) then
322
+ m1 = multiplicity_of_factor(x.numerator, prime_number)
323
+ m2 = multiplicity_of_factor(x.denominator, prime_number)
324
+ return m1 - m2
325
+
326
+ elsif (x.kind_of? LongDecimal)
327
+ m1 = multiplicity_of_factor(x.numerator, prime_number)
328
+ if (prime_number == 2 || prime_number == 5) then
329
+ return m1 - x.scale
330
+ else
331
+ return m1
332
+ end
333
+
334
+ elsif (x.kind_of? Integer)
335
+
336
+ power = gcd_with_high_power(x, prime_number)
337
+ if (power.abs < MAX_FLOATABLE) then
338
+ result = (Math.log(power) / Math.log(prime_number)).round
339
+ else
340
+ e = (Math.log(MAX_FLOATABLE) / Math.log(prime_number)).floor
341
+ result = 0
342
+ partial = prime_number ** e
343
+ while (power > partial) do
344
+ power /= partial
345
+ result += e
346
+ end
347
+ result += (Math.log(power) / Math.log(prime_number)).round
348
+ end
349
+ return result
350
+ else
351
+ raise TypeError, "type of x is not supported #{x.class} #{x.inpect}"
352
+ end
353
+ end
354
+
355
+ #
356
+ # method for calculating pi to the given number of digits after the
357
+ # decimal point.
358
+ # It works fine for 1000 or 2000 digits or so.
359
+ # This method could be optimized more, but if you really want to go
360
+ # for more digits, you will find a specialized and optimized program
361
+ # for this specific purpose, probably written in C or C++.
362
+ # Since calculation of pi is not what should typically be done with
363
+ # LongDecimal, you may consider this method to be the easter egg of
364
+ # LongDecimal. ;-)
365
+ #
366
+ def LongMath.calc_pi(prec, final_mode = LongDecimal::ROUND_HALF_DOWN)
367
+ mode = LongDecimal::ROUND_HALF_DOWN
368
+ iprec = 5*(prec+1)
369
+ sprec = (iprec >> 1) + 1
370
+ dprec = (prec+1) << 1
371
+
372
+ a = LongDecimal(1)
373
+ b = (1 / LongDecimal(2).sqrt(iprec,mode)).round_to_scale(iprec, mode)
374
+ c = LongDecimal(5,1)
375
+ k = 1
376
+ pow_k = 2
377
+
378
+ pi = 0
379
+ last_pi = 0
380
+ last_diff = 1
381
+
382
+ loop do
383
+ a, b = ((a + b) / 2).round_to_scale(sprec, mode), (a * b).round_to_scale(iprec, mode).sqrt(sprec, mode)
384
+ c = (c - pow_k * (a * a - b * b)).round_to_scale(iprec, mode)
385
+ pi = (2 * a * a / c).round_to_scale(sprec, mode)
386
+ diff = (pi - last_pi).round_to_scale(dprec, mode).abs
387
+ if (diff.zero? && last_diff.zero?) then
388
+ break
389
+ end
390
+ last_pi = pi
391
+ last_diff = diff
392
+ k += 1
393
+ pow_k = pow_k << 1
394
+ # puts("k=#{k} pi=#{pi.to_s}\nd=#{diff}\n\n")
395
+ end
396
+ pi.round_to_scale(prec, final_mode)
397
+ end
398
+
399
+ #
400
+ # calc the exponential function of x to the given precision as
401
+ # LongDecimal. Only supports values of x such that the result still
402
+ # fits into a float (x <= 709). This limitation is somewhat
403
+ # arbitrary, but it is enforced in order to avoid producing numbers
404
+ # with the exponential function that exceed the memory. It may be
405
+ # removed in future versions.
406
+ #
407
+ def LongMath.exp(x, prec, mode = LongDecimal::ROUND_HALF_DOWN)
408
+ check_is_ld(x, "x")
409
+ raise TypeError, "x=#{x.inspect} must not be greater #{MAX_EXP_ABLE}" unless x <= MAX_EXP_ABLE
410
+ check_is_prec(prec, "prec")
411
+ check_is_mode(mode, "mode")
412
+ exp_internal(x, prec, mode)
413
+ end
414
+
415
+ #
416
+ # private helper method for exponentiation
417
+ # calculate internal precision
418
+ #
419
+ def LongMath.calc_iprec_for_exp(x, prec)
420
+ iprec_extra = 0
421
+ if (x > 1) then
422
+ xf = x.to_f
423
+ iprec_extra = (xf / LOG10).abs
424
+ end
425
+ iprec = ((prec+10)*1.20 + iprec_extra).round
426
+ if (iprec < prec) then
427
+ iprec = prec
428
+ end
429
+ # puts("calc_iprec_for_exp: x=#{x} prec=#{prec} iprec=#{iprec} iprec_extra=#{iprec_extra}\n")
430
+ iprec
431
+ end
432
+
433
+ # private :calc_iprec_for_exp
434
+
435
+ #
436
+ # internal functionality of exp. exposes some more parameters, that
437
+ # should usually be set to defaut values, in order to allow better testing.
438
+ # do not actually call this method unless you are testing exp.
439
+ # create a bug report, if the default settings for the parameters do
440
+ # not work correctly
441
+ #
442
+ def LongMath.exp_internal(x, prec = nil, final_mode = LongDecimal::ROUND_HALF_DOWN, j = nil, k = nil, iprec = nil, mode = LongDecimal::ROUND_HALF_DOWN)
443
+ check_is_ld(x, "x")
444
+ if (prec == nil) then
445
+ prec = x.scale
446
+ end
447
+ check_is_prec(prec, "prec")
448
+
449
+ if (final_mode == nil)
450
+ final_mode = LongDecimal::ROUND_HALF_DOWN
451
+ end
452
+ check_is_mode(final_mode, "final_mode")
453
+ check_is_mode(mode, "mode")
454
+
455
+ # if the result would come out to zero anyway, cut the work
456
+ xi = x.to_i
457
+ if (xi < -LongMath::MAX_FLOATABLE) || -((xi.to_f - 1) / LOG10) > prec+1 then
458
+ return LongDecimal(25, prec+2).round_to_scale(prec, final_mode)
459
+ end
460
+
461
+ if j == nil || k == nil then
462
+ s1 = (prec * LOG10 / LOG2) ** (1.0/3.0)
463
+ if (j == nil) then
464
+ j = s1.round
465
+ end
466
+ if (k == nil) then
467
+ k = (s1 + Math.log([1, prec].max) / LOG2).round
468
+ end
469
+ if (x > 1) then
470
+ k += (Math.log(x.to_f) / LOG2).abs.round
471
+ end
472
+ end
473
+ if (j <= 0) then
474
+ j = 1
475
+ end
476
+ if (k < 0) then
477
+ k = 0
478
+ end
479
+ check_is_int(j, "j")
480
+ check_is_int(k, "k")
481
+
482
+ if (iprec == nil) then
483
+ iprec = calc_iprec_for_exp(x, prec)
484
+ end
485
+ check_is_prec(iprec, "iprec")
486
+ # puts("exp_internal: x=#{x} prec=#{prec} iprec=#{iprec}\n")
487
+
488
+ dprec = [ iprec, (prec + 1) << 1 ].min
489
+
490
+ x_k = (x / (1 << k)).round_to_scale(iprec, mode)
491
+ x_j = (x_k ** j).round_to_scale(iprec, mode)
492
+ s = [ LongDecimal(0) ] * j
493
+ t = LongDecimal(1)
494
+ last_t = 1
495
+ f = 0
496
+ loop do
497
+ j.times do |i|
498
+ s[i] += t
499
+ f += 1
500
+ t = (t / f).round_to_scale(iprec, mode)
501
+ end
502
+ t = (t * x_j).round_to_scale(iprec, mode)
503
+ break if (t.zero?)
504
+ tr = t.round_to_scale(dprec, LongDecimal::ROUND_DOWN).abs
505
+ break if (t.zero?)
506
+ tu = t.unit
507
+ break if (tr <= tu && last_t <= tu)
508
+ last_t = tr
509
+ end
510
+ x_i = 1
511
+ y_k = LongDecimal(0)
512
+ j.times do |i|
513
+ if (i > 0) then
514
+ x_i = (x_i * x_k).round_to_scale(iprec, mode)
515
+ end
516
+ # puts("y_k=#{y_k}\ni=#{i} j=#{j} k=#{k} x=#{x}\nx_k=#{x_k}\nx_j=#{x_j}\nx_i=#{x_i}\ns[i]=#{s[i]}\n\n")
517
+ y_k += (s[i] * x_i).round_to_scale(iprec, mode)
518
+ end
519
+ # puts("y_k = #{y_k}\n")
520
+ k.times do |i|
521
+ y_k = y_k.square.round_to_scale(iprec, mode)
522
+ # puts("i=#{i} y_k = #{y_k}\n")
523
+ end
524
+ y = y_k.round_to_scale(prec, final_mode)
525
+ y
526
+ end
527
+
528
+ #
529
+ # calculate the natural logarithm function of x to the given precision as
530
+ # LongDecimal.
531
+ #
532
+ def LongMath.log(x, prec, mode = LongDecimal::ROUND_HALF_DOWN)
533
+ check_is_ld(x, "x")
534
+ check_is_prec(prec, "prec")
535
+ check_is_mode(mode, "mode")
536
+ log_internal(x, prec, mode)
537
+ end
538
+
539
+ #
540
+ # calculate the base 10 logarithm of x to the given precision as
541
+ # LongDecimal.
542
+ #
543
+ def LongMath.log10(x, prec, mode = LongDecimal::ROUND_HALF_DOWN)
544
+ check_is_ld(x, "x")
545
+ check_is_prec(prec, "prec")
546
+ if (x.one?) then
547
+ return LongDecimal.zero!(prec)
548
+ end
549
+ check_is_mode(mode, "mode")
550
+ iprec = prec + 2
551
+ id = x.int_digits10
552
+ xx = x.move_point_left(id)
553
+ # puts("x=#{x} xx=#{xx} id=#{id} iprec=#{iprec}\n")
554
+ lnxx = log_internal(xx, iprec, mode)
555
+ ln10 = log_internal(10.to_ld, iprec, mode)
556
+ y = id + (lnxx / ln10).to_ld
557
+ return y.round_to_scale(prec, mode)
558
+ end
559
+
560
+ #
561
+ # calculate the base 2 logarithm of x to the given precision as
562
+ # LongDecimal.
563
+ #
564
+ def LongMath.log2(x, prec, mode = LongDecimal::ROUND_HALF_DOWN)
565
+ check_is_ld(x, "x")
566
+ check_is_prec(prec, "prec")
567
+ if (x.one?) then
568
+ return LongDecimal.zero!(prec)
569
+ end
570
+ check_is_mode(mode, "mode")
571
+ iprec = prec + 2
572
+ id = x.int_digits2
573
+ xx = (x / (1 << id)).round_to_scale(x.scale+id)
574
+ # puts("x=#{x} xx=#{xx} id=#{id} iprec=#{iprec}\n")
575
+ lnxx = log_internal(xx, iprec, mode)
576
+ ln2 = log_internal(2.to_ld, iprec, mode)
577
+ y = id + (lnxx / ln2).to_ld
578
+ end
579
+
580
+ #
581
+ # internal functionality of log. exposes some more parameters, that
582
+ # should usually be set to defaut values, in order to allow better testing.
583
+ # do not actually call this method unless you are testing log.
584
+ # create a bug report, if the default settings for the parameters do
585
+ # not work correctly
586
+ #
587
+ def LongMath.log_internal(x, prec = nil, final_mode = LongDecimal::ROUND_HALF_DOWN, iprec = nil, mode = LongDecimal::ROUND_HALF_DOWN)
588
+ check_is_ld(x)
589
+ raise TypeError, "x=#{x.inspect} must not be positive" unless x > 0
590
+ if (prec == nil) then
591
+ prec = x.scale
592
+ end
593
+ check_is_prec(prec, "prec")
594
+ if (x.one?) then
595
+ return LongDecimal.zero!(prec)
596
+ end
597
+
598
+ if (final_mode == nil)
599
+ final_mode = LongDecimal::ROUND_HALF_DOWN
600
+ end
601
+ check_is_mode(final_mode, "final_mode")
602
+ check_is_mode(mode, "mode")
603
+
604
+ if (iprec == nil) then
605
+ iprec = ((prec+10)*1.20).round
606
+ end
607
+ if (iprec < prec) then
608
+ iprec = prec
609
+ end
610
+ check_is_prec(iprec, "iprec")
611
+
612
+ # dprec = [ iprec - 1, (prec + 1) << 1 ].min
613
+ dprec = iprec - 1
614
+
615
+ y = 0
616
+ s = 1
617
+ if (x < 1) then
618
+ # puts("x=#{x} iprec=#{iprec}\n")
619
+ x = (1 / x).round_to_scale(iprec, mode)
620
+ s = -1
621
+ # puts("s=#{s} x=#{x} iprec=#{iprec}\n")
622
+ end
623
+ exp_part = 0
624
+ estimate = 0
625
+ while (x > MAX_FLOATABLE) do
626
+ if (exp_part == 0) then
627
+ estimate = MAX_EXP_ABLE.to_ld
628
+ exp_part = exp(estimate, iprec)
629
+ end
630
+ x = (x / exp_part).round_to_scale(iprec, mode)
631
+ if (s < 0) then
632
+ y -= estimate
633
+ else
634
+ y += estimate
635
+ end
636
+ end
637
+
638
+ delta = LongDecimal(1, 3)
639
+ while (x - 1).abs > delta do
640
+ # puts("too far from 1: x=#{x}\n")
641
+ xf = x.to_f
642
+ # puts("xf=#{xf}\n")
643
+ mlx = Math.log(xf)
644
+ # puts("log(xf)=#{mlx}\n")
645
+ estimate = mlx.to_ld.round_to_scale(20, mode)
646
+ exp_part = exp(estimate, iprec << 1)
647
+ # puts("y=#{y} s=#{s} est=#{estimate} part=#{exp_part} x=#{x}\n")
648
+ x = (x / exp_part).round_to_scale(iprec, mode)
649
+ # puts("divided by exp_part=#{exp_part}: #{x}\n")
650
+ if (s < 0) then
651
+ y -= estimate
652
+ else
653
+ y += estimate
654
+ end
655
+ # puts("y=#{y} s=#{s} est=#{estimate} part=#{exp_part} x=#{x}\n")
656
+ end
657
+
658
+ factor = 1
659
+ # delta = LongDecimal(1, (iprec.to_f**(1/3)).round)
660
+ # while (x - 1).abs > delta do
661
+ # x = sqrt(x)
662
+ # factor *= 2
663
+ # end
664
+
665
+ sum = 0
666
+ z = 1 - x
667
+ i = 1
668
+ p = 1.to_ld
669
+ d = 1.to_ld
670
+ until p.abs.round_to_scale(dprec, LongDecimal::ROUND_DOWN).zero? do
671
+ p = (p * z).round_to_scale(iprec, mode)
672
+ d = (p / i).round_to_scale(iprec, mode)
673
+ i += 1
674
+ sum += d
675
+
676
+ # puts("log_internal: s=#{sum} d=#{d} x=#{x} i=#{i} p=#{p} iprec=#{iprec} dprec=#{dprec}\n") if (i & 0x0f == 0x0f)
677
+ end
678
+
679
+ # puts("y=#{y} s=#{s} f=#{factor} sum=#{sum}\n")
680
+ y -= ((s * factor) * sum).round_to_scale(iprec, mode)
681
+ # puts("y=#{y} s=#{s} f=#{factor} sum=#{sum}\n")
682
+ return y.round_to_scale(prec, final_mode)
683
+
684
+ end
685
+
686
+ #
687
+ # calc the power of x with exponent y to the given precision as
688
+ # LongDecimal. Only supports values of y such that exp(y) still
689
+ # fits into a float (y <= 709)
690
+ #
691
+ def LongMath.power(x, y, prec, mode = LongDecimal::ROUND_HALF_DOWN)
692
+ check_is_ld(x, "x")
693
+ check_is_ld(y, "y")
694
+ raise TypeError, "y=#{y.inspect} must not be greater #{MAX_EXP_ABLE}" unless y <= MAX_EXP_ABLE
695
+ raise TypeError, "x=#{x.inspect} must not be greater #{MAX_FLOATABLE}" unless x <= MAX_FLOATABLE
696
+ raise TypeError, "x=#{x.inspect} must not positive" unless x > 0
697
+ check_is_prec(prec, "prec")
698
+ check_is_mode(mode, "mode")
699
+ LongMath.power_internal(x, y, prec, mode)
700
+ end
701
+
702
+ #
703
+ # internal functionality of exp. exposes some more parameters, that
704
+ # should usually be set to defaut values, in order to allow better testing.
705
+ # do not actually call this method unless you are testing exp.
706
+ # create a bug report, if the default settings for the parameters do
707
+ # not work correctly
708
+ #
709
+ def LongMath.power_internal(x, y, prec = nil, final_mode = LongDecimal::ROUND_HALF_DOWN, iprec = nil, mode = LongDecimal::ROUND_HALF_DOWN)
710
+ check_is_ld(x, "x")
711
+ if (prec == nil) then
712
+ prec = x.scale
713
+ end
714
+ check_is_prec(prec, "prec")
715
+
716
+ if (final_mode == nil)
717
+ final_mode = LongDecimal::ROUND_HALF_DOWN
718
+ end
719
+ check_is_mode(final_mode, "final_mode")
720
+ check_is_mode(mode, "mode")
721
+
722
+ logx_y_f = Math.log(x.to_f) * (y.to_f)
723
+
724
+ # iprec = (prec * 1.2 + 20 + (y.abs.to_f) * 1.5 * x.int_digits2).round
725
+ if (iprec == nil) then
726
+ iprec = calc_iprec_for_exp(logx_y_f, prec) + 2
727
+ end
728
+ # puts("power_internal: x=#{x} y=#{y} logx_y=#{logx_y_f} iprec=#{iprec} prec=#{prec}\n")
729
+ logx = log(x, iprec, mode)
730
+ logx_y = logx*y
731
+ xy = exp_internal(logx_y, prec + 1, mode)
732
+ # puts("power_internal: x=#{x} logx=#{logx} y=#{y} logx_y=#{logx_y} xy=#{xy} iprec=#{iprec} prec=#{prec}\n")
733
+ xy.round_to_scale(prec, final_mode)
734
+ end
735
+
736
+ end # LongMath
737
+
738
+ #
739
+ # class for holding fixed point long decimal numbers
740
+ # these can be considered as a pair of two integer. One contains the
741
+ # digits and the other one the position of the decimal point.
742
+ #
743
+ class LongDecimal < Numeric
744
+ @RCS_ID='-$Id: long-decimal.rb,v 1.1 2006/03/18 08:34:28 bk1 Exp $-'
745
+
746
+ include LongDecimalRoundingMode
747
+
748
+ # MINUS_ONE = LongDecimal(-1)
749
+ # ZERO = LongDecimal(0)
750
+ # ONE = LongDecimal(1)
751
+ # TWO = LongDecimal(2)
752
+ # TEN = LongDecimal(10)
753
+
754
+ #
755
+ # initialization
756
+ # parameters:
757
+ # 1. LongDecimal.new!(x) where x is a string or a number
758
+ # the resulting LongDecimal holds the number x, possibly rounded
759
+ # 2. LongDecimal.new!(x, s) where x is a string or a number and s is the scale
760
+ # the resulting LongDecimal holds the number x / 10**s
761
+ #
762
+ def LongDecimal.new!(x, s = 0)
763
+ new(x, s)
764
+ end
765
+
766
+ #
767
+ # creates a LongDecimal representing zero with the given number of
768
+ # digits after the decimal point (scale=s)
769
+ #
770
+ def LongDecimal.zero!(s = 0)
771
+ new(0, s)
772
+ end
773
+
774
+
775
+ #
776
+ # creates a LongDecimal representing one with the given number of
777
+ # digits after the decimal point (scale=s)
778
+ #
779
+ def LongDecimal.one!(s = 0)
780
+ new(1, s)
781
+ end
782
+
783
+
784
+ #
785
+ # creates a LongDecimal representing two with the given number of
786
+ # digits after the decimal point (scale=s)
787
+ #
788
+ def LongDecimal.two!(s = 0)
789
+ new(2*10**s, s)
790
+ end
791
+
792
+
793
+ #
794
+ # creates a LongDecimal representing ten with the given number of
795
+ # digits after the decimal point (scale=s)
796
+ #
797
+ def LongDecimal.ten!(s = 0)
798
+ new(10**(s+1), s)
799
+ end
800
+
801
+
802
+ #
803
+ # creates a LongDecimal representing minus one with the given number of
804
+ # digits after the decimal point (scale=s)
805
+ #
806
+ def LongDecimal.minus_one!(s = 0)
807
+ new(-1*10**s, s)
808
+ end
809
+
810
+
811
+ #
812
+ # creates a LongDecimal representing a power of ten with the given
813
+ # exponent e and with the given number of digits after the decimal
814
+ # point (scale=s)
815
+ #
816
+ def LongDecimal.power_of_ten!(e, s = 0)
817
+ LongMath.check_is_int(e, "e")
818
+ raise TypeError, "negative 1st arg \"#{e.inspect}\"" if e < 0
819
+ new(10**(s+e), s)
820
+ end
821
+
822
+
823
+ #
824
+ # initialization
825
+ # parameters:
826
+ # LongDecimal.new(x, s) where x is a string or a number and s is the scale
827
+ # the resulting LongDecimal holds the number x / 10**s
828
+ #
829
+ def initialize(x, s)
830
+
831
+ # handle some obvious errors with x first
832
+ raise TypeError, "non numeric 1st arg \"#{x.inspect}\"" if ! (x.kind_of? Numeric) && ! (x.kind_of? String)
833
+ # we could maybe even work with complex number, if their imaginary part is zero.
834
+ # but this is not so important to deal with, so we raise an error anyway.
835
+ raise TypeError, "complex numbers not supported \"#{x.inspect}\"" if x.kind_of? Complex
836
+
837
+ # handle some obvious errors with optional second parameter, if present
838
+ raise TypeError, "non integer 2nd arg \"#{s.inspect}\"" if ! s.kind_of? Integer
839
+ raise TypeError, "negative 2nd arg \"#{s.inspect}\"" if s < 0
840
+
841
+ # scale is the second parameter or 0 if it is missing
842
+ scale = s
843
+ # int_val is the integral value that is multiplied by some 10**-n
844
+ int_val = 0
845
+
846
+ if x.kind_of? Integer then
847
+ # integers are trivial to handle
848
+ int_val = x
849
+
850
+ elsif x.kind_of? Rational then
851
+ # rationals are rounded somehow
852
+ # we need to come up with a better rule here.
853
+ # if denominator is any product of powers of 2 and 5, we do not need to round
854
+ denom = x.denominator
855
+ mul_2 = LongMath.multiplicity_of_factor(denom, 2)
856
+ mul_5 = LongMath.multiplicity_of_factor(denom, 5)
857
+ iscale = [mul_2, mul_5].max
858
+ scale += iscale
859
+ denom /= 2 ** mul_2
860
+ denom /= 5 ** mul_5
861
+ iscale2 = Math.log10(denom).ceil
862
+ scale += iscale2
863
+ # int_val = (x * 10 ** scale).to_i
864
+ int_val = (x * 10 ** (iscale2+iscale)).to_i
865
+
866
+ else
867
+ # we assume a string or a floating point number
868
+ # floating point number or BigDecimal is converted to string, so
869
+ # we only deal with strings
870
+ # this operation is not so common, so there is no urgent need to
871
+ # optimize it
872
+ num_str = x.to_s
873
+ len = num_str.length
874
+
875
+ # handle the obvious error that string is empty
876
+ raise TypeError, "1st arg must not be empty string. \"#{num_str.inspect}\"" if len == 0
877
+
878
+ # remove spaces and underscores
879
+ num_str.gsub! /\s/, ""
880
+ num_str.gsub! /_/, ""
881
+
882
+ # handle sign
883
+ num_str.gsub! /^\+/, ""
884
+ negative = false
885
+ if num_str.gsub! /^-/, "" then
886
+ negative = true
887
+ end
888
+
889
+ # split in parts before and after decimal point
890
+ num_arr = num_str.split /\./
891
+ if num_arr.length > 2 then
892
+ raise TypeError, "1st arg contains more than one . \"#{num_str.inspect}\""
893
+ end
894
+ num_int = num_arr[0]
895
+ num_rem = num_arr[1]
896
+ num_frac = nil
897
+ num_exp = nil
898
+ unless num_rem.nil? then
899
+ num_arr = num_rem.split /[Ee]/
900
+ num_frac = num_arr[0]
901
+ num_exp = num_arr[1]
902
+ end
903
+
904
+ if num_frac.nil? then
905
+ num_frac = ""
906
+ end
907
+
908
+ if num_exp.nil? || num_exp.empty? then
909
+ num_exp = "0"
910
+ end
911
+ num_exp = num_exp.to_i
912
+ iscale = num_frac.length - num_exp
913
+ scale += iscale
914
+ int_val = (num_int + num_frac).to_i
915
+ if negative then
916
+ int_val = -int_val
917
+ end
918
+ end
919
+ @scale = scale
920
+ @int_val = int_val
921
+
922
+ end # initialize
923
+
924
+ attr_reader :int_val, :scale
925
+
926
+ # #
927
+ # # get the integer value of self, disregarding the decimal point.
928
+ # # Mostly for internal use.
929
+ # #
930
+ # def int_val
931
+ # @int_val
932
+ # end
933
+
934
+ # #
935
+ # # get the scale, i.e. the position of the decimal point.
936
+ # # Mostly for internal use.
937
+ # #
938
+ # def scale
939
+ # @scale
940
+ # end
941
+
942
+ #
943
+ # alter scale (changes self)
944
+ #
945
+ # only for internal use:
946
+ # use round_to_scale instead
947
+ #
948
+ def scale=(s)
949
+ raise TypeError, "non integer arg \"#{s.inspect}\"" if ! s.kind_of? Integer
950
+ raise TypeError, "negative arg \"#{s.inspect}\"" if s < 0
951
+
952
+ # do not work too hard, if scale does not really change.
953
+ unless @scale == s then
954
+ # multiply int_val by a power of 10 in order to compensate for
955
+ # the change of scale and to keep number in the same order of magnitude.
956
+ d = s - @scale
957
+ f = 10 ** (d.abs)
958
+ if (d >= 0) then
959
+ @int_val = (@int_val * f).to_i
960
+ else
961
+ # here we actually do rounding
962
+ @int_val = (@int_val / f).to_i
963
+ end
964
+ @scale = s
965
+ end
966
+ end
967
+
968
+ protected :scale=
969
+
970
+ #
971
+ # create copy of self with different scale
972
+ # param1: new_scale new scale for result
973
+ # param2: mode rounding mode to be applied when information is
974
+ # lost. defaults to ROUND_UNNECESSARY, which
975
+ # means that an exception is thrown if rounding
976
+ # would actually loose any information.
977
+ #
978
+ def round_to_scale(new_scale, mode = ROUND_UNNECESSARY)
979
+
980
+ raise TypeError, "new_scale #{new_scale.inspect} must be integer" unless new_scale.kind_of? Integer
981
+ raise TypeError, "new_scale #{new_scale.inspect} must be >= 0" unless new_scale >= 0
982
+ raise TypeError, "mode #{mode.inspect} must be legal rounding mode" unless mode.kind_of? RoundingModeClass
983
+ if @scale == new_scale then
984
+ self
985
+ else
986
+ diff = new_scale - scale
987
+ factor = 10 ** (diff.abs)
988
+ if (diff > 0) then
989
+ # we become more precise, no rounding issues
990
+ new_int_val = int_val * factor
991
+ else
992
+ quot, rem = int_val.divmod(factor)
993
+ if (rem == 0) then
994
+ new_int_val = quot
995
+ elsif (mode == ROUND_UNNECESSARY) then
996
+ raise ArgumentError, "mode ROUND_UNNECESSARY not applicable, remainder #{rem.to_s} is not zero"
997
+ else
998
+ return LongDecimalQuot(self, LongDecimal(1)).round_to_scale(new_scale, mode)
999
+ end
1000
+ end
1001
+ LongDecimal(new_int_val, new_scale)
1002
+ end
1003
+ end
1004
+
1005
+ #
1006
+ # convert self into String, which is the decimal representation.
1007
+ # Use trailing zeros, if int_val has them.
1008
+
1009
+ # optional parameter shown_scale is the number of digits after the
1010
+ # decimal point. Defaults to the scale of self.
1011
+ # optional parameter mode ist the rounding mode to be applied.
1012
+ # Defaults to ROUND_UNNECESSARY, in which case an exception is
1013
+ # thrown if rounding is actually necessary.
1014
+ # optional parameter base is the base to be used when expressing
1015
+ # self as string. defaults to 10.
1016
+ #
1017
+ def to_s(shown_scale = @scale, mode = ROUND_UNNECESSARY, base = 10)
1018
+ if (base == 10) then
1019
+ if (shown_scale == @scale)
1020
+ to_s_10
1021
+ else
1022
+ s = self.round_to_scale(shown_scale, mode)
1023
+ s.to_s_10
1024
+ end
1025
+ else
1026
+ # base is not 10
1027
+ unless (base.kind_of? Integer) && 2 <= base && base <= 36 then
1028
+ raise TypeError, "base must be integer between 2 and 36"
1029
+ end
1030
+ quot = (self.move_point_right(scale) * base ** shown_scale) / 10 ** scale
1031
+ p(quot)
1032
+ rounded = quot.round_to_scale(0, mode)
1033
+ p(rounded)
1034
+ rounded.to_s_internal(base, shown_scale)
1035
+ end
1036
+ end
1037
+
1038
+ #
1039
+ # internal helper method, converts self to string in decimal system
1040
+ # with default settings.
1041
+ #
1042
+ def to_s_10
1043
+ to_s_internal(10, scale)
1044
+ end
1045
+
1046
+ #
1047
+ # internal helper method, converts self to string in any number system
1048
+ #
1049
+ def to_s_internal(b, sc)
1050
+ sg = sgn
1051
+ i = int_val.abs
1052
+ str = i.to_s(b)
1053
+ if sc > 0 then
1054
+ missing = sc - str.length + 1
1055
+ if missing > 0 then
1056
+ str = ("0" * missing) + str
1057
+ end
1058
+ str[-sc, 0] = "."
1059
+ end
1060
+ str = "-" + str if sg < 0
1061
+ str
1062
+ end
1063
+
1064
+ protected :to_s_10
1065
+ protected :to_s_internal
1066
+
1067
+ #
1068
+ # convert self into Rational
1069
+ # this works quite straitforward. use int_val as numerator and a
1070
+ # power of 10 as denominator
1071
+ #
1072
+ def to_r
1073
+ Rational(numerator, denominator)
1074
+ end
1075
+
1076
+ #
1077
+ # convert self into Float
1078
+ # this works straitforward by dividing int_val by power of 10 in
1079
+ # float-arithmetic, in all cases where numerator and denominator are
1080
+ # within the ranges expressable as Floats. Goes via string
1081
+ # representation otherwise.
1082
+ #
1083
+ def to_f
1084
+ divisor = denominator
1085
+ if (divisor == 1) then
1086
+ return numerator.to_f
1087
+ elsif int_val.abs <= LongMath::MAX_FLOATABLE then
1088
+ if (divisor.abs > LongMath::MAX_FLOATABLE) then
1089
+ return 0.0
1090
+ else
1091
+ f = int_val.to_f
1092
+ return f / divisor
1093
+ end
1094
+ elsif numerator.abs < divisor
1095
+ # self is between -1 and 1
1096
+ # factor = numerator.abs.div(LongMath::MAX_FLOATABLE)
1097
+ # digits = factor.to_ld.int_digits10
1098
+ # return LongDecimal(numerator.div(10**digits), scale -digits).to_f
1099
+ return self.to_s.to_f
1100
+ else
1101
+ # s2 = [scale.div(2), 1].max
1102
+ # return LongDecimal(numerator.div(10**s2), scale - s2).to_f
1103
+ return self.to_s.to_f
1104
+ end
1105
+ end
1106
+
1107
+ #
1108
+ # convert self into Integer
1109
+ # This may loose information. In most cases it is preferred to
1110
+ # control this by calling round_to_scale first and then applying
1111
+ # to_i when the number represented by self is actually an integer.
1112
+ #
1113
+ def to_i
1114
+ numerator.div(denominator)
1115
+ end
1116
+
1117
+ #
1118
+ # convert self into LongDecimal (returns self)
1119
+ #
1120
+ def to_ld
1121
+ self
1122
+ end
1123
+
1124
+ #
1125
+ # convert selt into BigDecimal
1126
+ #
1127
+ def to_bd
1128
+ # this operation is probably not used so heavily, so we can live with a
1129
+ # string as an intermediate step.
1130
+ BigDecimal(self.to_s)
1131
+ end
1132
+
1133
+ #
1134
+ # LongDecimals can be seen as a fraction with a power of 10 as
1135
+ # denominator for compatibility with other numeric classes this
1136
+ # method is included, returning 10**scale.
1137
+ # Please observe that there may be common factors of numerator and
1138
+ # denominator in case of LongDecimal, which does not occur in case
1139
+ # of Rational
1140
+ #
1141
+ def denominator
1142
+ 10**scale
1143
+ end
1144
+
1145
+ #
1146
+ # LongDecimals can be seen as a fraction with its int_val as its
1147
+ # numerator
1148
+ # Please observe that there may be common factors of numerator and
1149
+ # denominator in case of LongDecimal, which does not occur in case
1150
+ # of Rational
1151
+ #
1152
+ alias numerator int_val
1153
+
1154
+ #
1155
+ # number of binary digits before the decimal point, not counting a single 0.
1156
+ # 0.xxx -> 0
1157
+ # 1.xxx -> 1
1158
+ # 2.xxx -> 2
1159
+ # 4.xxx -> 3
1160
+ # 8.xxx -> 4
1161
+ # ...
1162
+ #
1163
+ def int_digits2
1164
+ int_part = self.to_i.abs
1165
+ if int_part.zero? then
1166
+ return 0
1167
+ end
1168
+
1169
+ n = int_part.size * 8 - 31
1170
+ int_part = int_part >> n
1171
+ until int_part.zero? do
1172
+ int_part = int_part >> 1
1173
+ n += 1
1174
+ end
1175
+ n
1176
+ end
1177
+
1178
+ #
1179
+ # number of decimal digits before the decimal point, not counting a
1180
+ # single 0.
1181
+ # 0.xxx -> 0
1182
+ # 1.xxx -> 1
1183
+ # 10.xxx -> 2
1184
+ # ...
1185
+ #
1186
+ def int_digits10
1187
+ int_part = self.to_i.abs
1188
+ if int_part.zero? then
1189
+ return 0
1190
+ end
1191
+
1192
+ id = 1
1193
+ powers = []
1194
+ power = 10
1195
+ idx = 0
1196
+ until int_part.zero? do
1197
+ expon = 1 << idx
1198
+ powers[idx] = power
1199
+ break if int_part < power
1200
+ id += expon
1201
+ int_part = (int_part / power).to_i
1202
+ idx += 1
1203
+ power = power * power
1204
+ end
1205
+ until int_part < 10 do
1206
+ idx -= 1
1207
+ expon = 1 << idx
1208
+ power = powers[idx]
1209
+ # puts("i=#{int_part} p=#{power}\n")
1210
+ while int_part >= power
1211
+ id += expon
1212
+ int_part = (int_part / power).to_i
1213
+ end
1214
+ end
1215
+ id
1216
+ end
1217
+
1218
+ #
1219
+ # before adding or subtracting two LongDecimal numbers
1220
+ # it is mandatory to set them to the same scale. The maximum of the
1221
+ # two summands is used, in order to avoid loosing any information.
1222
+ # this method is mostly for internal use
1223
+ #
1224
+ def equalize_scale(other)
1225
+ o, s = coerce(other)
1226
+ if (s.kind_of? LongDecimal) then
1227
+ # make sure Floats do not mess up our number of significant digits when adding
1228
+ if (other.kind_of? Float) then
1229
+ o = o.round_to_scale(s.scale, ROUND_HALF_UP)
1230
+ else
1231
+ new_scale = [s.scale, o.scale].max
1232
+ s = s.round_to_scale(new_scale)
1233
+ o = o.round_to_scale(new_scale)
1234
+ end
1235
+ end
1236
+ return s, o
1237
+ end
1238
+
1239
+ #
1240
+ # before dividing two LongDecimal numbers, it is mandatory to set
1241
+ # make them both to integers, so the result is simply expressable as
1242
+ # a rational
1243
+ # this method is mostly for internal use
1244
+ #
1245
+ def anti_equalize_scale(other)
1246
+ o, s = coerce(other)
1247
+ if (s.kind_of? LongDecimal) then
1248
+ exponent = [s.scale, o.scale].max
1249
+ factor = 10**exponent
1250
+ s *= factor
1251
+ o *= factor
1252
+ s = s.round_to_scale(0)
1253
+ o = o.round_to_scale(0)
1254
+ end
1255
+ return s, o
1256
+ end
1257
+
1258
+ #
1259
+ # successor as needed for using LongDecimal in ranges
1260
+ # it needs to be observed that this is usually not an increment by
1261
+ # 1, but by 1/10**scale.
1262
+ #
1263
+ def succ
1264
+ LongDecimal(int_val + 1, scale)
1265
+ end
1266
+
1267
+ alias next succ
1268
+
1269
+ #
1270
+ # predecessor (opposite of successor)
1271
+ # it needs to be observed that this is usually not an decrement by
1272
+ # 1, but by 1/10**scale.
1273
+ #
1274
+ def pred
1275
+ LongDecimal(int_val - 1, scale)
1276
+ end
1277
+
1278
+ #
1279
+ # self + 1
1280
+ #
1281
+ def inc
1282
+ self + 1
1283
+ end
1284
+
1285
+ #
1286
+ # self - 1
1287
+ #
1288
+ def dec
1289
+ self - 1
1290
+ end
1291
+
1292
+ #
1293
+ # self += 1
1294
+ #
1295
+ def inc!
1296
+ @int_val += denominator
1297
+ end
1298
+
1299
+ #
1300
+ # self -= 1
1301
+ #
1302
+ def dec!
1303
+ @int_val -= denominator
1304
+ end
1305
+
1306
+ #
1307
+ # return the unit by which self is incremented by succ
1308
+ #
1309
+ def unit
1310
+ LongDecimal(1, scale)
1311
+ end
1312
+
1313
+ #
1314
+ # apply unary +
1315
+ # (returns self)
1316
+ #
1317
+ def +@
1318
+ self
1319
+ end
1320
+
1321
+ #
1322
+ # apply unary -
1323
+ # (returns negated self)
1324
+ #
1325
+ def -@
1326
+ if self.zero? then
1327
+ self
1328
+ else
1329
+ LongDecimal(-int_val, scale)
1330
+ end
1331
+ end
1332
+
1333
+ #
1334
+ # add two numbers
1335
+ # if both can immediately be expressed as LongDecimal, the result is
1336
+ # a LongDecimal as well. The number of digits after the decimal
1337
+ # point is the max of the scales of the summands
1338
+ # if LongDecimal does not cover the two summands, call addition of
1339
+ # Complex, Float or LongRationalQuot
1340
+ #
1341
+ def +(other)
1342
+ s, o = equalize_scale(other)
1343
+ if s.kind_of? LongDecimal then
1344
+ LongDecimal(s.int_val + o.int_val, s.scale)
1345
+ else
1346
+ s + o
1347
+ end
1348
+ end
1349
+
1350
+ #
1351
+ # subtract two numbers
1352
+ # if both can immediately be expressed as LongDecimal, the result is
1353
+ # a LongDecimal as well. The number of digits after the decimal
1354
+ # point is the max of the scales of self and other.
1355
+ # if LongDecimal does not cover self and other, the subtraction of
1356
+ # Complex, Float or LongRationalQuot is used
1357
+ #
1358
+ def -(other)
1359
+ s, o = equalize_scale(other)
1360
+ if s.kind_of? LongDecimal then
1361
+ LongDecimal(s.int_val - o.int_val, s.scale)
1362
+ else
1363
+ s - o
1364
+ end
1365
+ end
1366
+
1367
+ #
1368
+ # multiply two numbers
1369
+ # if both can immediately be expressed as LongDecimal, the result is
1370
+ # a LongDecimal as well. The number of digits after the decimal
1371
+ # point is the sum of the scales of both factors.
1372
+ # if LongDecimal does not cover self and other, the multiplication of
1373
+ # Complex, Float or LongRationalQuot is used
1374
+ #
1375
+ def *(other)
1376
+ o, s = coerce(other)
1377
+ if s.kind_of? LongDecimal then
1378
+ LongDecimal(s.int_val * o.int_val, s.scale + o.scale)
1379
+ else
1380
+ s * o
1381
+ end
1382
+ end
1383
+
1384
+ #
1385
+ # divide self by other and round result to scale of self using the
1386
+ # given rounding mode
1387
+ #
1388
+ def divide(other, rounding_mode)
1389
+ divide_s(other, nil, rounding_mode)
1390
+ end
1391
+
1392
+ #
1393
+ # divide self by other and round result to new_scale using the
1394
+ # given rounding mode. If new_scale is nil, use scale of self.
1395
+ #
1396
+ def divide_s(other, new_scale, rounding_mode)
1397
+ q = self / other
1398
+ if (q.kind_of? Float) then
1399
+ q = LongDecimal(q)
1400
+ end
1401
+ if (q.kind_of? LongDecimal) || (q.kind_of? LongDecimalQuot) then
1402
+ if (new_scale.nil?) then
1403
+ new_scale = q.scale
1404
+ end
1405
+ q.round_to_scale(new_scale, rounding_mode)
1406
+ else
1407
+ q
1408
+ end
1409
+ end
1410
+
1411
+ #
1412
+ # divide self by other and return result as Rational, if other
1413
+ # allowed exact calculations.
1414
+ #
1415
+ def rdiv(other)
1416
+ q = self / other
1417
+ if (q.kind_of? LongDecimalQuot) then
1418
+ q.to_r
1419
+ else
1420
+ q
1421
+ end
1422
+ end
1423
+
1424
+ #
1425
+ # divide self by other and return result as LongDecimalQuot
1426
+ # because division does not have an obvious rounding rule like
1427
+ # addition, subtraction and multiplication, the result needs to be
1428
+ # rounded afterwards to become a LongDecimal again. This way
1429
+ # calculations can still be done in the natural readable way using +,
1430
+ # -, *, and /, but the rounding can be provided later.
1431
+ # It is very important in complicated calculations put the rounding
1432
+ # steps in the right places, usually after having performed a division.
1433
+ #
1434
+ def /(other)
1435
+ o, s = coerce(other)
1436
+ if (s.kind_of? LongDecimal) then
1437
+ LongDecimalQuot(s, o)
1438
+ else
1439
+ s / o
1440
+ end
1441
+ end
1442
+
1443
+ #
1444
+ # power of self (LongDecimal) with other.
1445
+ # if other is expressable as non-negative integer, the power is what
1446
+ # would be obtained by successive multiplications.
1447
+ # if other is expressable as negative integer, the power is a
1448
+ # LongDecimalQuot as would result by successive division, but with
1449
+ # the same scale as the positive power would get. Explicit rounding
1450
+ # is needed to convert into a LongDecimal again
1451
+ # in all other cases, self is converted into a Rational prior to
1452
+ # applying power, usually resulting in a Float as power.
1453
+ #
1454
+ def **(other)
1455
+ if ((other.kind_of? LongDecimal) || (other.kind_of? LongDecimalQuot)) && other.is_int? then
1456
+ other = other.to_i
1457
+ end
1458
+ if other.kind_of? Integer then
1459
+ if other >= 0 then
1460
+ LongDecimal(int_val ** other, scale * other)
1461
+ else
1462
+ abs_other = -other
1463
+ new_scale = abs_other * scale
1464
+ LongDecimalQuot(Rational(10 ** new_scale, int_val ** abs_other), new_scale)
1465
+ end
1466
+ else
1467
+ if (other.kind_of? LongDecimal) || (other.kind_of? LongDecimalQuot) then
1468
+ other = other.to_r
1469
+ end
1470
+ self.to_r ** other
1471
+ end
1472
+ end
1473
+
1474
+ #
1475
+ # do integer division with remainder, returning two values
1476
+ #
1477
+ def divmod(other)
1478
+ if (other.kind_of? Complex) then
1479
+ raise TypeError, "divmod not supported for Complex"
1480
+ end
1481
+ q = (self / other).to_i
1482
+ return q, self - other * q
1483
+ end
1484
+
1485
+ #
1486
+ # remainder of integer division by other
1487
+ #
1488
+ def %(other)
1489
+ q, r = divmod other
1490
+ r
1491
+ end
1492
+
1493
+ #
1494
+ # performs bitwise AND between self and other
1495
+ #
1496
+ def &(other)
1497
+ s, o = equalize_scale(other)
1498
+ if s.kind_of? LongDecimal then
1499
+ LongDecimal(s.int_val & o.int_val, s.scale)
1500
+ else
1501
+ s & o
1502
+ end
1503
+ end
1504
+
1505
+ #
1506
+ # performs bitwise OR between self and other
1507
+ #
1508
+ def |(other)
1509
+ s, o = equalize_scale(other)
1510
+ if s.kind_of? LongDecimal then
1511
+ LongDecimal(s.int_val | o.int_val, s.scale)
1512
+ else
1513
+ s | o
1514
+ end
1515
+ end
1516
+
1517
+ #
1518
+ # performs bitwise XOR between self and other
1519
+ #
1520
+ def ^(other)
1521
+ s, o = equalize_scale(other)
1522
+ if s.kind_of? LongDecimal then
1523
+ LongDecimal(s.int_val ^ o.int_val, s.scale)
1524
+ else
1525
+ s ^ o
1526
+ end
1527
+ end
1528
+
1529
+ #
1530
+ # bitwise inversion
1531
+ #
1532
+ def ~
1533
+ LongDecimal(~int_val, scale)
1534
+ end
1535
+
1536
+ #
1537
+ # performs bitwise left shift of self by other
1538
+ #
1539
+ def <<(other)
1540
+ unless (other.kind_of? Integer) && other >= 0 then
1541
+ raise TypeError, "cannot shift by something other than integer >= 0"
1542
+ end
1543
+ LongDecimal(s.int_val << other, s.scale)
1544
+ end
1545
+
1546
+ #
1547
+ # performs bitwise right shift of self by other
1548
+ #
1549
+ def >>(other)
1550
+ unless (other.kind_of? Integer) && other >= 0 then
1551
+ raise TypeError, "cannot shift by something other than integer >= 0"
1552
+ end
1553
+ LongDecimal(s.int_val >> other, s.scale)
1554
+ end
1555
+
1556
+ #
1557
+ # gets binary digit of self
1558
+ #
1559
+ def [](other)
1560
+ int_val[other]
1561
+ end
1562
+
1563
+ #
1564
+ # gets size of int_val
1565
+ #
1566
+ def size
1567
+ int_val.size
1568
+ end
1569
+
1570
+ #
1571
+ # divide by 10**n
1572
+ #
1573
+ def move_point_left(n)
1574
+ raise TypeError, "only implemented for Fixnum" unless n.kind_of? Fixnum
1575
+ if (n >= 0) then
1576
+ move_point_left_int(n)
1577
+ else
1578
+ move_point_right_int(-n)
1579
+ end
1580
+ end
1581
+
1582
+ #
1583
+ # multiply by 10**n
1584
+ #
1585
+ def move_point_right(n)
1586
+ raise TypeError, "only implemented for Fixnum" unless n.kind_of? Fixnum
1587
+ if (n < 0) then
1588
+ move_point_left_int(-n)
1589
+ else
1590
+ move_point_right_int(n)
1591
+ end
1592
+ end
1593
+
1594
+ #
1595
+ # internal method
1596
+ # divide by 10**n
1597
+ #
1598
+ def move_point_left_int(n)
1599
+ raise TypeError, "only implemented for Fixnum >= 0" unless n >= 0
1600
+ LongDecimal(int_val, scale + n)
1601
+ end
1602
+
1603
+ #
1604
+ # internal method
1605
+ # multiply by 10**n
1606
+ #
1607
+ def move_point_right_int(n)
1608
+ raise TypeError, "only implemented for Fixnum >= 0" unless n >= 0
1609
+ if (n > scale) then
1610
+ LongDecimal(int_val * 10**(n-scale), 0)
1611
+ else
1612
+ LongDecimal(int_val, scale-n)
1613
+ end
1614
+ end
1615
+
1616
+ protected :move_point_left_int, :move_point_right_int
1617
+
1618
+ #
1619
+ # calculate the square of self
1620
+ #
1621
+ def square
1622
+ self * self
1623
+ end
1624
+
1625
+ def sqrt(new_scale, rounding_mode)
1626
+ raise TypeError, "new_scale #{new_scale.inspect} must be integer" unless new_scale.kind_of? Integer
1627
+ raise TypeError, "new_scale #{new_scale.inspect} must be >= 0" unless new_scale >= 0
1628
+ raise TypeError, "mode #{mode.inspect} must be legal rounding mode" unless rounding_mode.kind_of? RoundingModeClass
1629
+
1630
+ new_scale1 = new_scale + 1
1631
+ old_scale = (new_scale1 << 1)
1632
+ x = round_to_scale(old_scale, rounding_mode)
1633
+ root, rem = LongMath.sqrtb_with_remainder(x.int_val)
1634
+ if (rem > 0 && (rounding_mode == ROUND_HALF_EVEN || rounding_mode == ROUND_HALF_DOWN)) then
1635
+ rounding_mode = ROUND_HALF_UP
1636
+ end
1637
+ y = LongDecimal(root, new_scale1)
1638
+ y.round_to_scale(new_scale, rounding_mode)
1639
+ end
1640
+
1641
+
1642
+ #
1643
+ # calculate the multiplicative inverse
1644
+ #
1645
+ def reciprocal
1646
+ 1 / self
1647
+ end
1648
+
1649
+ alias inverse reciprocal
1650
+
1651
+ #
1652
+ # Absolute value
1653
+ #
1654
+ def abs
1655
+ LongDecimal(int_val.abs, scale)
1656
+ end
1657
+
1658
+ #
1659
+ # square of absolute value
1660
+ # happens to be the square
1661
+ #
1662
+ alias abs2 square
1663
+
1664
+ #
1665
+ # Compares the two numbers.
1666
+ # returns -1 if self < other
1667
+ # 0 if self-other = 0
1668
+ # +1 if self > other
1669
+ # it needs to be observed, that
1670
+ # x == y implies (x <=> y) == 0
1671
+ # but not
1672
+ # (x <=> y) == 0 implies x == y
1673
+ # because == also takes the scale into account and considers two
1674
+ # numbers only equal, if they have the same number of potentially
1675
+ # zero digits after the decimal point.
1676
+ #
1677
+ def <=> (other)
1678
+ diff = (self - other)
1679
+ if (diff.kind_of? LongDecimal) || (diff.kind_of? LongDecimalQuot) then
1680
+ diff.sgn
1681
+ else
1682
+ diff <=> 0
1683
+ end
1684
+ end
1685
+
1686
+ #
1687
+ # <=>-comparison for the scales
1688
+ #
1689
+ def scale_ufo(other)
1690
+ raise TypeError, "only works for LongDecimal and LongDecimalQuot" unless (other.kind_of? LongDecimal) || (other.kind_of? LongDecimalQuot)
1691
+ self.scale <=> other.scale
1692
+ end
1693
+
1694
+ #
1695
+ # ==-comparison for the scales
1696
+ #
1697
+ def scale_equal(other)
1698
+ scale_ufo(other).zero?
1699
+ end
1700
+
1701
+ #
1702
+ # return a pair o, s resembling other, self, but potentially
1703
+ # converted to compatible types and ready for
1704
+ # arithmetic operations.
1705
+ #
1706
+ def coerce(other)
1707
+ if other.kind_of? LongDecimal then
1708
+ return other, self
1709
+ elsif other.kind_of? LongDecimalQuot then
1710
+ return other, LongDecimalQuot(self.to_r, scale)
1711
+ elsif other.kind_of? Rational then
1712
+ sc = scale
1713
+ o = LongDecimalQuot(other, sc)
1714
+ s = LongDecimalQuot(self.to_r, sc)
1715
+ return o, s
1716
+ elsif (other.kind_of? Integer) || (other.kind_of? Float) then
1717
+ other = LongDecimal(other)
1718
+ if (other.scale > scale) then
1719
+ other = other.round_to_scale(scale, ROUND_HALF_UP)
1720
+ end
1721
+ return other, self
1722
+ elsif other.kind_of? BigDecimal then
1723
+ s, o = other.coerce(self.to_bd)
1724
+ return o, s
1725
+ elsif other.kind_of? Complex then
1726
+ # s, o = other.coerce(Complex(self.to_bd, 0))
1727
+ s, o = other.coerce(Complex(self.to_f, 0))
1728
+ return o, s
1729
+ elsif (other.kind_of? Float) && size > 8 then
1730
+ return coerce(BigDecimal(other.to_s))
1731
+ elsif other.kind_of? Numeric then
1732
+ s, o = other.coerce(self.to_f)
1733
+ return o, s
1734
+ else
1735
+ raise TypeError, "unsupported type #{other.inspect} for coerce of LongDecimal"
1736
+ end
1737
+ end
1738
+
1739
+ #
1740
+ # is self expressable as an integer without loss of digits?
1741
+ #
1742
+ def is_int?
1743
+ scale == 0 || int_val % 10**scale == 0
1744
+ end
1745
+
1746
+ #
1747
+ # get the sign of self
1748
+ # -1 if self < 0
1749
+ # 0 if self is 0 (with any number of 0s after the decimal point)
1750
+ # +1 if self > 0
1751
+ #
1752
+ def sgn
1753
+ int_val <=> 0
1754
+ end
1755
+
1756
+ alias signum sgn
1757
+ alias sign sgn
1758
+
1759
+ #
1760
+ # comparison of self with other for equality
1761
+ # takes into account the values expressed by self and other and the
1762
+ # equality of the number of digits.
1763
+ #
1764
+ def ==(other)
1765
+ # (other.kind_of? LongDecimal) && (self <=> other) == 0 && self.scale == other.scale
1766
+ (other.kind_of? LongDecimal) && self.int_val == other.int_val && self.scale == other.scale
1767
+ end
1768
+
1769
+ #
1770
+ # check if the number expressed by self is 0 (zero)
1771
+ # with any number of 0s after the decimal point.
1772
+ #
1773
+ def zero?
1774
+ int_val.zero?
1775
+ end
1776
+
1777
+ #
1778
+ # check if the number expressed by self is 1 (one)
1779
+ # with any number of 0s after the decimal point.
1780
+ #
1781
+ def one?
1782
+ (self-1).zero?
1783
+ end
1784
+
1785
+ #
1786
+ # Returns a hash code for the complex number.
1787
+ #
1788
+ def hash
1789
+ int_val.hash ^ scale.hash
1790
+ end
1791
+
1792
+ #
1793
+ # Returns "<tt>LongDecimal(<i>int_val</i>, <i>scale</i>)</tt>".
1794
+ #
1795
+ def inspect
1796
+ sprintf("LongDecimal(%s, %s)", int_val.inspect, scale.inspect)
1797
+ end
1798
+
1799
+ end # LongDecimal
1800
+
1801
+ #
1802
+ # This class is used for storing intermediate results after having
1803
+ # performed a division. The division cannot be completed without
1804
+ # providing additional information on how to round the result.
1805
+ #
1806
+ class LongDecimalQuot < Numeric
1807
+
1808
+ @RCS_ID='-$Id: long-decimal.rb,v 1.1 2006/03/18 08:34:28 bk1 Exp $-'
1809
+
1810
+ include LongDecimalRoundingMode
1811
+
1812
+ #
1813
+ # constructor
1814
+ # first, second is either a pair of LongDecimals or a Rational and an Integer
1815
+ # The resulting LongDecimal will contain a rational obtained by
1816
+ # dividing the two LongDecimals or by taking the Rational as it is.
1817
+ # The scale is there to provide a default rounding precision for
1818
+ # conversion to LongDecimal, but it has no influence on the value
1819
+ # expressed by the LongDecimalQuot
1820
+ #
1821
+ def LongDecimalQuot.new!(first, second)
1822
+ new(first, second)
1823
+ end
1824
+
1825
+ #
1826
+ # create a new LongDecimalQuot from a rational and a scale or a
1827
+ # pair of LongDecimals
1828
+ #
1829
+ def initialize(first, second)
1830
+ if ((first.kind_of? Rational) || (first.kind_of? Integer)) && (second.kind_of? Integer) then
1831
+ @rat = Rational(first.numerator, first.denominator)
1832
+ @scale = second
1833
+ elsif (first.kind_of? LongDecimal) && (second.kind_of? LongDecimal) then
1834
+ orig_scale = first.scale
1835
+ first, second = first.anti_equalize_scale(second)
1836
+ @rat = Rational(first.to_i, second.to_i)
1837
+ @scale = orig_scale
1838
+ else
1839
+ raise TypeError, "parameters must be (LongDecimal, LongDecimal) or (Rational, Integer): first=#{first.inspect} second=#{second.inspect}";
1840
+ end
1841
+ end
1842
+
1843
+ attr_reader :scale, :rat
1844
+
1845
+ # def scale
1846
+ # @scale
1847
+ # end
1848
+
1849
+ # def rat
1850
+ # @rat
1851
+ # end
1852
+
1853
+ #
1854
+ # numerator of the included rational number.
1855
+ # LongDecimals should duck type like Rationals
1856
+ #
1857
+ def numerator
1858
+ rat.numerator
1859
+ end
1860
+
1861
+ #
1862
+ # denominator of the included rational number.
1863
+ # LongDecimals should duck type like Rationals
1864
+ #
1865
+ def denominator
1866
+ rat.denominator
1867
+ end
1868
+
1869
+ #
1870
+ # alter scale (only for internal use)
1871
+ #
1872
+ def scale=(s)
1873
+ raise TypeError, "non integer arg \"#{s.inspect}\"" if ! s.kind_of? Integer
1874
+ raise TypeError, "negative arg \"#{s.inspect}\"" if s < 0
1875
+ @scale = s
1876
+ end
1877
+
1878
+ private :scale=
1879
+
1880
+ #
1881
+ # conversion to string. Based on the conversion of Rational
1882
+ #
1883
+ def to_s
1884
+ str = @rat.to_s
1885
+ str + "[" + scale.to_s + "]"
1886
+ end
1887
+
1888
+ #
1889
+ # conversion to rational
1890
+ #
1891
+ def to_r
1892
+ Rational(numerator, denominator)
1893
+ end
1894
+
1895
+ #
1896
+ # convert into Float
1897
+ #
1898
+ def to_f
1899
+ to_r.to_f
1900
+ end
1901
+
1902
+ #
1903
+ # convert into Integer
1904
+ #
1905
+ def to_i
1906
+ to_r.to_i
1907
+ end
1908
+
1909
+ #
1910
+ # conversion to LongDecimal using the internal scale
1911
+ #
1912
+ def to_ld
1913
+ round_to_scale(scale, ROUND_HALF_UP)
1914
+ end
1915
+
1916
+ #
1917
+ # unary plus returns self
1918
+ #
1919
+ def +@
1920
+ self
1921
+ end
1922
+
1923
+ #
1924
+ # unary minus returns negation of self
1925
+ # leaves self unchanged.
1926
+ #
1927
+ def -@
1928
+ if self.zero? then
1929
+ self
1930
+ else
1931
+ LongDecimalQuot(-rat, scale)
1932
+ end
1933
+ end
1934
+
1935
+ #
1936
+ # addition
1937
+ # if other can be converted into LongDecimalQuot, add as
1938
+ # LongDecimalQuot, using the addition of Rationals
1939
+ # otherwise use BigDecimal, Complex or Float
1940
+ #
1941
+ def +(other)
1942
+ o, s = coerce(other)
1943
+ if (s.kind_of? LongDecimalQuot) then
1944
+ LongDecimalQuot(s.rat + o.rat, [s.scale, o.scale].max)
1945
+ else
1946
+ s + o
1947
+ end
1948
+ end
1949
+
1950
+ def -(other)
1951
+ o, s = coerce(other)
1952
+ if (s.kind_of? LongDecimalQuot) then
1953
+ LongDecimalQuot(s.rat - o.rat, [s.scale, o.scale].max)
1954
+ else
1955
+ s - o
1956
+ end
1957
+ end
1958
+
1959
+ def *(other)
1960
+ o, s = coerce(other)
1961
+ if (s.kind_of? LongDecimalQuot) then
1962
+ LongDecimalQuot(s.rat * o.rat, s.scale + o.scale)
1963
+ else
1964
+ s * o
1965
+ end
1966
+ end
1967
+
1968
+ def /(other)
1969
+ o, s = coerce(other)
1970
+ if (s.kind_of? LongDecimalQuot) then
1971
+ LongDecimalQuot(s.rat / o.rat, scale)
1972
+ else
1973
+ s / o
1974
+ end
1975
+ end
1976
+
1977
+ def **(other)
1978
+ if (other.kind_of? LongDecimal) || (other.kind_of? LongDecimalQuot) then
1979
+ if other.is_int? then
1980
+ other = other.to_i
1981
+ else
1982
+ other = other.to_r
1983
+ end
1984
+ end
1985
+ rat_result = rat ** other
1986
+ if (rat_result.kind_of? Rational) then
1987
+ if (other.kind_of? Integer) && other >= 0 then
1988
+ new_scale = scale * other
1989
+ else
1990
+ new_scale = scale
1991
+ end
1992
+ LongDecimalQuot(rat_result, new_scale)
1993
+ else
1994
+ rat_result
1995
+ end
1996
+ end
1997
+
1998
+ def divmod(other)
1999
+ if (other.kind_of? Complex) then
2000
+ raise TypeError, "divmod not supported for Complex"
2001
+ end
2002
+ q = (self / other).to_i
2003
+ return q, self - other * q
2004
+ end
2005
+
2006
+ def %(other)
2007
+ q, r = divmod other
2008
+ r
2009
+ end
2010
+
2011
+ # def %(other)
2012
+ # o, s = coerce(other)
2013
+ # if (s.kind_of? LongDecimalQuot) then
2014
+ # LongDecimalQuot(s.rat % o.rat, scale)
2015
+ # else
2016
+ # s % o
2017
+ # end
2018
+ # end
2019
+
2020
+ def square
2021
+ self * self
2022
+ end
2023
+
2024
+ #
2025
+ # calculate the multiplicative inverse
2026
+ #
2027
+ def reciprocal
2028
+ 1 / self
2029
+ end
2030
+
2031
+ #
2032
+ # Absolute value
2033
+ #
2034
+ def abs
2035
+ LongDecimalQuot(rat.abs, scale)
2036
+ end
2037
+
2038
+ def abs2
2039
+ self.abs.square
2040
+ end
2041
+
2042
+ #
2043
+ # convert LongDecimalQuot to LongDecimal with the given precision
2044
+ # and the given rounding mode
2045
+ #
2046
+ def round_to_scale(new_scale = @scale, mode = ROUND_UNNECESSARY)
2047
+
2048
+ raise TypeError, "new_scale #{new_scale.inspect} must be integer" unless new_scale.kind_of? Integer
2049
+ raise TypeError, "new_scale #{new_scale.inspect} must be >= 0" unless new_scale >= 0
2050
+ raise TypeError, "mode #{mode.inspect} must be legal rounding mode" unless mode.kind_of? RoundingModeClass
2051
+
2052
+ factor = 10**new_scale
2053
+ sign_quot = numerator <=> 0
2054
+ if sign_quot == 0 then
2055
+ return LongDecimal(0, new_scale)
2056
+ end
2057
+ prod = numerator * factor
2058
+ divisor = denominator
2059
+ quot, rem = prod.divmod(divisor)
2060
+ sign_rem = rem <=> 0
2061
+ if (sign_rem == 0)
2062
+ return LongDecimal(quot, new_scale)
2063
+ end
2064
+ raise Error, "signs do not match self=#{self.to_s} f=#{factor} prod=#{prod} divisor=#{divisor} quot=#{quot} rem=#{rem}" if sign_rem <= 0
2065
+ if (sign_quot < 0) then
2066
+ rem -= divisor
2067
+ quot += 1
2068
+ sign_rem = rem <=> 0
2069
+ raise Error, "signs do not match self=#{self.to_s} f=#{factor} prod=#{prod} divisor=#{divisor} quot=#{quot} rem=#{rem}" if sign_rem >= 0
2070
+ end
2071
+
2072
+ if mode == ROUND_UNNECESSARY then
2073
+ raise ArgumentError, "mode ROUND_UNNECESSARY not applicable, remainder #{rem.to_s} is not zero"
2074
+ end
2075
+
2076
+ if (mode == ROUND_CEILING)
2077
+ mode = (sign_quot > 0) ? ROUND_UP : ROUND_DOWN
2078
+ elsif (mode == ROUND_FLOOR)
2079
+ mode = (sign_quot < 0) ? ROUND_UP : ROUND_DOWN
2080
+ else
2081
+ abs_rem = rem.abs
2082
+ half = (abs_rem << 1) <=> denominator
2083
+ if (mode == ROUND_HALF_UP || mode == ROUND_HALF_DOWN || mode == ROUND_HALF_EVEN) then
2084
+ if (half < 0) then
2085
+ mode = ROUND_DOWN
2086
+ elsif half > 0 then
2087
+ mode = ROUND_UP
2088
+ else
2089
+ # half == 0
2090
+ if (mode == ROUND_HALF_UP) then
2091
+ mode = ROUND_UP
2092
+ elsif (mode == ROUND_HALF_DOWN) then
2093
+ mode = ROUND_DOWN
2094
+ else
2095
+ # mode == ROUND_HALF_EVEN
2096
+ mode = (quot[0] == 1 ? ROUND_UP : ROUND_DOWN)
2097
+ end
2098
+ end
2099
+ end
2100
+ end
2101
+
2102
+ if mode == ROUND_UP
2103
+ quot += sign_quot
2104
+ end
2105
+ new_int_val = quot
2106
+ LongDecimal(new_int_val, new_scale)
2107
+ end
2108
+
2109
+ #
2110
+ # prepare binary operation of other with LongDecimalQuot
2111
+ # Integer, LongDecimal, Rational and LongDecimalQuot can be
2112
+ # expressed as LongDecimalQuot, using the scale of self in case of
2113
+ # Integer and Rational. Floats can be approximated by LongDecimals
2114
+ # and thus be expressed as LongDecimalQuot
2115
+ # In case of BigDecimal, Complex or any unknown type, convert self
2116
+ # to BigDecimal or Float.
2117
+ #
2118
+ def coerce(other)
2119
+ if other.kind_of? LongDecimal then
2120
+ return LongDecimalQuot(other.to_r, other.scale), self
2121
+ elsif other.kind_of? LongDecimalQuot then
2122
+ return other, self
2123
+ elsif other.kind_of? Rational then
2124
+ s = scale
2125
+ return LongDecimalQuot(other, s), self
2126
+ elsif (other.kind_of? Integer) then
2127
+ return LongDecimalQuot(other.to_r, scale), self
2128
+ elsif other.kind_of? Float then
2129
+ return LongDecimalQuot(other.to_ld.to_r, scale), self
2130
+ elsif other.kind_of? BigDecimal then
2131
+ s, o = other.coerce(self.to_bd)
2132
+ elsif other.kind_of? Numeric then
2133
+ s, o = other.coerce(self.to_f)
2134
+ return o, s
2135
+ else
2136
+ raise TypeError, "unsupported type #{other.inspect} for coerce of LongDecimalQuot"
2137
+ end
2138
+ end
2139
+
2140
+ #
2141
+ # compare two numbers for equality.
2142
+ # The LongDecimalQuot self is considered == to other if and only if
2143
+ # other is also LongDecimalQuot, expresses the same value and has the
2144
+ # same scale.
2145
+ # It needs to be observed that scale does not influence the value expressed
2146
+ # by the number, but only how rouding is performed by default if no
2147
+ # explicit number of digits after the decimal point is given. But
2148
+ # scale needs to match for equality.
2149
+ #
2150
+ def ==(other)
2151
+ (other.kind_of? LongDecimalQuot) && (self <=> other) == 0 && self.scale == other.scale
2152
+ end
2153
+
2154
+ #
2155
+ # Compares the two numbers for < and > etc.
2156
+ #
2157
+ def <=> (other)
2158
+ diff = (self - other)
2159
+ if (diff.kind_of? LongDecimal) || (diff.kind_of? LongDecimalQuot) then
2160
+ diff.sgn
2161
+ else
2162
+ diff <=> 0
2163
+ end
2164
+ end
2165
+
2166
+ #
2167
+ # compare scales with <=>
2168
+ #
2169
+ def scale_ufo(other)
2170
+ raise TypeError, "only works for LongDecimal and LongDecimalQuot" unless (other.kind_of? LongDecimal) || (other.kind_of? LongDecimalQuot)
2171
+ self.scale <=> other.scale
2172
+ end
2173
+
2174
+ #
2175
+ # check if scales are equal
2176
+ #
2177
+ def scale_equal(other)
2178
+ scale_ufo(other).zero?
2179
+ end
2180
+
2181
+ #
2182
+ # is self expressable as an integer without loss of digits?
2183
+ #
2184
+ def is_int?
2185
+ denominator == 1
2186
+ end
2187
+
2188
+ #
2189
+ # sign of self
2190
+ #
2191
+ def sgn
2192
+ numerator <=> 0
2193
+ end
2194
+ alias signum sgn
2195
+ alias sign sgn
2196
+
2197
+ #
2198
+ # Returns a hash code for the complex number.
2199
+ #
2200
+ def hash
2201
+ rat.hash ^ scale.hash
2202
+ end
2203
+
2204
+
2205
+ #
2206
+ # Returns "<tt>LongDecimalQuot(<i>int_val</i>, <i>scale</i>, <i>num</i>, <i>denom</i>)</tt>".
2207
+ #
2208
+ def inspect
2209
+ sprintf("LongDecimalQuot(Rational(%s, %s), %s)", numerator.inspect, denominator.inspect, scale.inspect)
2210
+ end
2211
+
2212
+ end # LongDecimalQuot
2213
+
2214
+ #
2215
+ # Creates a LongDecimal number. +a+ and +b+ should be Numeric.
2216
+ #
2217
+ def LongDecimal(a, b = 0)
2218
+ if b == 0 && (a.kind_of? LongDecimal) then
2219
+ a
2220
+ else
2221
+ LongDecimal.new!(a, b)
2222
+ end
2223
+ end
2224
+
2225
+ #
2226
+ # construct a LongDecimalQuot from the given parameters
2227
+ # 1st case: both are LongDecimals
2228
+ # 2nd case: first is Rational, second is scale
2229
+ #
2230
+ def LongDecimalQuot(first, second)
2231
+ LongDecimalQuot.new!(first, second)
2232
+ end
2233
+
2234
+
2235
+ class Numeric
2236
+
2237
+ #
2238
+ # convert self to LongDecimal
2239
+ #
2240
+ def to_ld
2241
+ LongDecimal(self)
2242
+ end
2243
+
2244
+ end # Numeric
2245
+
2246
+ # end of file long-decimal.rb