sq_decimal.cpp 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598
  1. #include "mpdecimal.h"
  2. #include "squirrel.h"
  3. #include <string.h>
  4. SQ_OPT_STRING_STRLEN();
  5. static const SQChar sq_decimal_ctx_TAG[] = _SC("DecimalCtx");
  6. #define SQ_PUSH_DECIMAL_CTX_TAG(v) sq_pushstring(v,sq_decimal_ctx_TAG,SIZEOF_SQCHAR_STRING(sq_decimal_ctx_TAG));
  7. static const SQChar sq_decimal_TAG[] = _SC("Decimal");
  8. #define SQ_PUSH_DECIMAL_TAG(v) sq_pushstring(v,sq_decimal_TAG,SIZEOF_SQCHAR_STRING(sq_decimal_TAG))
  9. static const SQChar sq_context_static[] = _SC("context");
  10. #define SQ_PUSH_CONTEXT_STATIC(v) sq_pushstring(v, sq_context_static, SIZEOF_SQCHAR_STRING(sq_context_static));
  11. #define GET_DecimalCtx_INSTANCE(v, idx) SQ_GET_INSTANCE_VAR(v, idx, mpd_context_t, ctx, sq_decimal_ctx_TAG)
  12. #define GET_Decimal_INSTANCE(v, idx) SQ_GET_INSTANCE_VAR(v, idx, mpd_t, dec, sq_decimal_TAG)
  13. #define GET_Decimal_INSTANCE2(v, idx) SQ_GET_INSTANCE_VAR(v, idx, mpd_t, dec2, sq_decimal_TAG)
  14. static SQRESULT sq_DecimalCtx_release_hook(SQUserPointer p, SQInteger size, void */*ep*/) {
  15. mpd_context_t *ctx = (mpd_context_t *)p;
  16. if(ctx) sq_free(ctx, sizeof(mpd_context_t));
  17. return 0;
  18. }
  19. /*
  20. ** Creates a new DecimalCtx.
  21. */
  22. static SQRESULT sq_DecimalCtx_constructor (HSQUIRRELVM v) {
  23. SQ_FUNC_VARS(v);
  24. GET_DecimalCtx_INSTANCE(v, 1);
  25. SQ_OPT_INTEGER(v, 2, prec, 8);
  26. if(prec < 0) return sq_throwerror(v, _SC("invalid precision (%d)"), prec);
  27. ctx = (mpd_context_t *)sq_malloc(sizeof(mpd_context_t));
  28. mpd_init(ctx, prec);
  29. sq_setinstanceup(v, 1, ctx);
  30. sq_setreleasehook(v, 1, sq_DecimalCtx_release_hook);
  31. return 1;
  32. }
  33. static SQRESULT sq_DecimalCtx_prec(HSQUIRRELVM v)
  34. {
  35. SQ_FUNC_VARS(v);
  36. GET_DecimalCtx_INSTANCE(v, 1);
  37. if(_top_ > 1){
  38. SQ_GET_INTEGER(v, 2, prec);
  39. if(prec < 0) return sq_throwerror(v, _SC("invalid precision (%d)"), prec);
  40. mpd_qsetprec(ctx, prec);
  41. return 0;
  42. }
  43. else sq_pushinteger(v, mpd_getprec(ctx));
  44. return 1;
  45. }
  46. static SQRESULT sq_DecimalCtx_emax(HSQUIRRELVM v)
  47. {
  48. SQ_FUNC_VARS(v);
  49. GET_DecimalCtx_INSTANCE(v, 1);
  50. if(_top_ > 1){
  51. SQ_GET_INTEGER(v, 2, emax);
  52. if(emax < 0) return sq_throwerror(v, _SC("invalid emax (%d)"), emax);
  53. mpd_qsetemax(ctx, emax);
  54. return 0;
  55. }
  56. else sq_pushinteger(v, mpd_getemax(ctx));
  57. return 1;
  58. }
  59. static SQRESULT sq_DecimalCtx_emin(HSQUIRRELVM v)
  60. {
  61. SQ_FUNC_VARS(v);
  62. GET_DecimalCtx_INSTANCE(v, 1);
  63. if(_top_ > 1){
  64. SQ_GET_INTEGER(v, 2, emin);
  65. if(emin < 0) return sq_throwerror(v, _SC("invalid emin (%d)"), emin);
  66. mpd_qsetemin(ctx, emin);
  67. return 0;
  68. }
  69. else sq_pushinteger(v, mpd_getemin(ctx));
  70. return 1;
  71. }
  72. static SQRESULT sq_DecimalCtx_round(HSQUIRRELVM v)
  73. {
  74. SQ_FUNC_VARS(v);
  75. GET_DecimalCtx_INSTANCE(v, 1);
  76. if(_top_ > 1){
  77. SQ_GET_INTEGER(v, 2, round);
  78. if(round < 0) return sq_throwerror(v, _SC("invalid round (%d)"), round);
  79. mpd_qsetround(ctx, round);
  80. return 0;
  81. }
  82. else sq_pushinteger(v, mpd_getround(ctx));
  83. return 1;
  84. }
  85. static SQRESULT sq_DecimalCtx_traps(HSQUIRRELVM v)
  86. {
  87. SQ_FUNC_VARS(v);
  88. GET_DecimalCtx_INSTANCE(v, 1);
  89. if(_top_ > 1){
  90. SQ_GET_INTEGER(v, 2, flags);
  91. if(flags < 0) return sq_throwerror(v, _SC("invalid traps (%d)"), flags);
  92. mpd_qsettraps(ctx, flags);
  93. return 0;
  94. }
  95. else sq_pushinteger(v, mpd_gettraps(ctx));
  96. return 1;
  97. }
  98. static SQRESULT sq_DecimalCtx_status(HSQUIRRELVM v)
  99. {
  100. SQ_FUNC_VARS(v);
  101. GET_DecimalCtx_INSTANCE(v, 1);
  102. if(_top_ > 1){
  103. SQ_GET_INTEGER(v, 2, status);
  104. if(status < 0) return sq_throwerror(v, _SC("invalid status (%d)"), status);
  105. mpd_qsetstatus(ctx, status);
  106. return 0;
  107. }
  108. else sq_pushinteger(v, mpd_getstatus(ctx));
  109. return 1;
  110. }
  111. static SQRESULT sq_DecimalCtx_clamp(HSQUIRRELVM v)
  112. {
  113. SQ_FUNC_VARS(v);
  114. GET_DecimalCtx_INSTANCE(v, 1);
  115. if(_top_ > 1){
  116. SQ_GET_INTEGER(v, 2, clamp);
  117. if(clamp < 0) return sq_throwerror(v, _SC("invalid clamp (%d)"), clamp);
  118. mpd_qsetclamp(ctx, clamp);
  119. return 0;
  120. }
  121. else sq_pushinteger(v, mpd_getclamp(ctx));
  122. return 1;
  123. }
  124. static SQRESULT sq_DecimalCtx_cr(HSQUIRRELVM v)
  125. {
  126. SQ_FUNC_VARS(v);
  127. GET_DecimalCtx_INSTANCE(v, 1);
  128. if(_top_ > 1){
  129. SQ_GET_INTEGER(v, 2, cr);
  130. if(cr < 0) return sq_throwerror(v, _SC("invalid cr (%d)"), cr);
  131. mpd_qsetcr(ctx, cr);
  132. return 0;
  133. }
  134. else sq_pushinteger(v, mpd_getcr(ctx));
  135. return 1;
  136. }
  137. #define _DECL_FUNC(name,nparams,tycheck) {_SC(#name),sq_DecimalCtx_##name,nparams,tycheck}
  138. static SQRegFunction DecimalCtx_methods[] =
  139. {
  140. _DECL_FUNC(constructor,-1,_SC("xi")),
  141. _DECL_FUNC(prec,-1,_SC("xi")),
  142. _DECL_FUNC(emax,-1,_SC("xi")),
  143. _DECL_FUNC(emin,-1,_SC("xi")),
  144. _DECL_FUNC(round,-1,_SC("xi")),
  145. _DECL_FUNC(traps,-1,_SC("xi")),
  146. _DECL_FUNC(status,-1,_SC("xi")),
  147. _DECL_FUNC(clamp,-1,_SC("xi")),
  148. _DECL_FUNC(cr,-1,_SC("xi")),
  149. {0,0}
  150. };
  151. #undef _DECL_FUNC
  152. static mpd_context_t * sq_get_global_ctx(HSQUIRRELVM v, SQInteger idx)
  153. {
  154. SQ_PUSH_CONTEXT_STATIC(v);
  155. sq_get(v, idx);
  156. mpd_context_t *ctx = 0;
  157. sq_getinstanceup(v, -1, (void**)&ctx, (void*)sq_decimal_ctx_TAG);
  158. sq_poptop(v);
  159. return ctx;
  160. }
  161. static SQRESULT sq_Decimal_error(HSQUIRRELVM v, uint32_t status) {
  162. const SQChar *error = _SC("MPD_??");
  163. #define CASE_ERROR(n) case n: error = #n; break;
  164. switch(status){
  165. CASE_ERROR(MPD_Clamped);
  166. CASE_ERROR(MPD_Conversion_syntax);
  167. CASE_ERROR(MPD_Division_by_zero );
  168. CASE_ERROR(MPD_Division_impossible);
  169. CASE_ERROR(MPD_Division_undefined);
  170. CASE_ERROR(MPD_Fpu_error);
  171. CASE_ERROR(MPD_Inexact);
  172. CASE_ERROR(MPD_Invalid_context);
  173. CASE_ERROR(MPD_Invalid_operation);
  174. CASE_ERROR(MPD_Malloc_error);
  175. CASE_ERROR(MPD_Not_implemented);
  176. CASE_ERROR(MPD_Overflow);
  177. CASE_ERROR(MPD_Rounded);
  178. CASE_ERROR(MPD_Subnormal);
  179. CASE_ERROR(MPD_Underflow);
  180. }
  181. #undef CASE_ERROR
  182. return sq_throwerror(v, error);
  183. }
  184. static SQRESULT sq_Decimal_set_from(HSQUIRRELVM v, SQInteger idx, mpd_context_t *ctx, mpd_t *dec, uint32_t *status){
  185. SQInteger _rc_;
  186. switch(sq_gettype(v, idx)){
  187. case OT_INSTANCE:{
  188. GET_Decimal_INSTANCE2(v, idx);
  189. mpd_qcopy(dec, dec2, status);
  190. }
  191. case OT_INTEGER:{
  192. SQ_GET_INTEGER(v, idx, iparam);
  193. mpd_qset_i32(dec, iparam, ctx, status);
  194. }
  195. break;
  196. case OT_STRING:{
  197. SQ_GET_STRING(v, idx, str);
  198. mpd_qset_string(dec, str, ctx, status);
  199. }
  200. break;
  201. case OT_FLOAT:{
  202. SQ_GET_FLOAT(v, idx, fparam);
  203. char buf[32];
  204. snprintf(buf, sizeof(buf), "%f", fparam);
  205. mpd_qset_string(dec, buf, ctx, status);
  206. }
  207. break;
  208. default:
  209. return sq_throwerror(v, _SC("invalid type (%s) to convert to decimal"), sq_gettypename(v, idx));
  210. }
  211. return SQ_OK;
  212. }
  213. static SQRESULT sq_Decimal_release_hook(SQUserPointer p, SQInteger size, void */*ep*/) {
  214. mpd_t *dec = (mpd_t *)p;
  215. if(dec) mpd_del(dec);
  216. return 0;
  217. }
  218. /*
  219. ** Creates a new Decimal.
  220. */
  221. static SQRESULT sq_Decimal_constructor (HSQUIRRELVM v) {
  222. uint32_t status = 0;
  223. mpd_context_t *ctx = sq_get_global_ctx(v, 1);
  224. mpd_t *dec = mpd_new(ctx);
  225. if(sq_gettop(v) > 1){
  226. if(sq_Decimal_set_from(v, 2, ctx, dec, &status) != SQ_OK) return SQ_ERROR;
  227. }
  228. else mpd_qset_i32(dec, 0, ctx, &status);
  229. ctx->status |= status;
  230. if (status&ctx->traps) {
  231. mpd_del(dec);
  232. return sq_Decimal_error(v, status);
  233. }
  234. sq_setinstanceup(v, 1, dec);
  235. sq_setreleasehook(v, 1, sq_Decimal_release_hook);
  236. return 1;
  237. }
  238. static SQRESULT sq_Decimal_set(HSQUIRRELVM v)
  239. {
  240. SQ_FUNC_VARS_NO_TOP(v);
  241. GET_Decimal_INSTANCE(v, 1);
  242. uint32_t status = 0;
  243. mpd_context_t *ctx = sq_get_global_ctx(v, 1);
  244. if(sq_Decimal_set_from(v, 2, ctx, dec, &status) != SQ_OK) return SQ_ERROR;
  245. ctx->status |= status;
  246. if (status&ctx->traps) {
  247. return sq_Decimal_error(v, status);
  248. }
  249. sq_settop(v, 1); //returns itself
  250. return 1;
  251. }
  252. static SQRESULT sq_Decimal_new_for_dec (HSQUIRRELVM v, mpd_t *dec, mpd_context_t *ctx, uint32_t status) {
  253. //mpd_addstatus_raise(ctx, status);
  254. ctx->status |= status;
  255. if (status&ctx->traps) {
  256. mpd_del(dec);
  257. return sq_Decimal_error(v, status);
  258. }
  259. sq_pushstring(v, sq_decimal_TAG, -1);
  260. sq_getonroottable(v);
  261. sq_createinstance(v, -1);
  262. sq_setinstanceup(v, -1, dec);
  263. sq_setreleasehook(v, -1, sq_Decimal_release_hook);
  264. return 1;
  265. }
  266. static SQRESULT sq_Decimal_tostring(HSQUIRRELVM v)
  267. {
  268. SQ_FUNC_VARS_NO_TOP(v);
  269. GET_Decimal_INSTANCE(v, 1);
  270. char *decstring = mpd_to_eng(dec, 1);
  271. sq_pushstring(v, decstring, -1);
  272. if (decstring) mpd_free(decstring);
  273. return 1;
  274. }
  275. static SQRESULT sq_Decimal__add(HSQUIRRELVM v)
  276. {
  277. SQ_FUNC_VARS_NO_TOP(v);
  278. GET_Decimal_INSTANCE(v, 1);
  279. GET_Decimal_INSTANCE2(v, 2);
  280. mpd_context_t *ctx = sq_get_global_ctx(v, 1);
  281. mpd_t *result = mpd_new(ctx);
  282. uint32_t status = 0;
  283. mpd_qadd(result, dec, dec2, ctx, &status);
  284. return sq_Decimal_new_for_dec(v, result, ctx, status);
  285. }
  286. static SQRESULT sq_Decimal__sub(HSQUIRRELVM v)
  287. {
  288. SQ_FUNC_VARS_NO_TOP(v);
  289. GET_Decimal_INSTANCE(v, 1);
  290. GET_Decimal_INSTANCE2(v, 2);
  291. mpd_context_t *ctx = sq_get_global_ctx(v, 1);
  292. mpd_t *result = mpd_new(ctx);
  293. uint32_t status = 0;
  294. mpd_qsub(result, dec, dec2, ctx, &status);
  295. return sq_Decimal_new_for_dec(v, result, ctx, status);
  296. }
  297. static SQRESULT sq_Decimal__mul(HSQUIRRELVM v)
  298. {
  299. SQ_FUNC_VARS_NO_TOP(v);
  300. GET_Decimal_INSTANCE(v, 1);
  301. GET_Decimal_INSTANCE2(v, 2);
  302. mpd_context_t *ctx = sq_get_global_ctx(v, 1);
  303. mpd_t *result = mpd_new(ctx);
  304. uint32_t status = 0;
  305. mpd_qmul(result, dec, dec2, ctx, &status);
  306. return sq_Decimal_new_for_dec(v, result, ctx, status);
  307. }
  308. static SQRESULT sq_Decimal__div(HSQUIRRELVM v)
  309. {
  310. SQ_FUNC_VARS_NO_TOP(v);
  311. GET_Decimal_INSTANCE(v, 1);
  312. GET_Decimal_INSTANCE2(v, 2);
  313. mpd_context_t *ctx = sq_get_global_ctx(v, 1);
  314. mpd_t *result = mpd_new(ctx);
  315. uint32_t status = 0;
  316. mpd_qdiv(result, dec, dec2, ctx, &status);
  317. return sq_Decimal_new_for_dec(v, result, ctx, status);
  318. }
  319. static SQRESULT sq_Decimal__modulo(HSQUIRRELVM v)
  320. {
  321. SQ_FUNC_VARS_NO_TOP(v);
  322. GET_Decimal_INSTANCE(v, 1);
  323. GET_Decimal_INSTANCE2(v, 2);
  324. mpd_context_t *ctx = sq_get_global_ctx(v, 1);
  325. mpd_t *result = mpd_new(ctx);
  326. uint32_t status = 0;
  327. mpd_qrem(result, dec, dec2, ctx, &status);
  328. return sq_Decimal_new_for_dec(v, result, ctx, status);
  329. }
  330. static SQRESULT sq_Decimal__unm(HSQUIRRELVM v)
  331. {
  332. SQ_FUNC_VARS_NO_TOP(v);
  333. GET_Decimal_INSTANCE(v, 1);
  334. mpd_context_t *ctx = sq_get_global_ctx(v, 1);
  335. mpd_t *result = mpd_new(ctx);
  336. uint32_t status = 0;
  337. mpd_qminus(result, dec, ctx, &status);
  338. return sq_Decimal_new_for_dec(v, result, ctx, status);
  339. }
  340. static SQRESULT sq_Decimal__cmp(HSQUIRRELVM v)
  341. {
  342. SQ_FUNC_VARS_NO_TOP(v);
  343. GET_Decimal_INSTANCE(v, 1);
  344. GET_Decimal_INSTANCE2(v, 2);
  345. mpd_context_t *ctx = sq_get_global_ctx(v, 1);
  346. sq_pushinteger(v, mpd_cmp(dec, dec2, ctx));
  347. return 1;
  348. }
  349. static SQRESULT sq_Decimal_abs(HSQUIRRELVM v)
  350. {
  351. SQ_FUNC_VARS_NO_TOP(v);
  352. GET_Decimal_INSTANCE(v, 1);
  353. mpd_context_t *ctx = sq_get_global_ctx(v, 1);
  354. mpd_t *result = mpd_new(ctx);
  355. uint32_t status = 0;
  356. mpd_qabs(result, dec, ctx, &status);
  357. return sq_Decimal_new_for_dec(v, result, ctx, status);
  358. }
  359. static SQRESULT sq_Decimal_max(HSQUIRRELVM v)
  360. {
  361. SQ_FUNC_VARS_NO_TOP(v);
  362. GET_Decimal_INSTANCE(v, 1);
  363. GET_Decimal_INSTANCE2(v, 2);
  364. mpd_context_t *ctx = sq_get_global_ctx(v, 1);
  365. mpd_t *result = mpd_new(ctx);
  366. uint32_t status = 0;
  367. mpd_qmax(result, dec, dec2, ctx, &status);
  368. return sq_Decimal_new_for_dec(v, result, ctx, status);
  369. }
  370. static SQRESULT sq_Decimal_min(HSQUIRRELVM v)
  371. {
  372. SQ_FUNC_VARS_NO_TOP(v);
  373. GET_Decimal_INSTANCE(v, 1);
  374. GET_Decimal_INSTANCE2(v, 2);
  375. mpd_context_t *ctx = sq_get_global_ctx(v, 1);
  376. mpd_t *result = mpd_new(ctx);
  377. uint32_t status = 0;
  378. mpd_qmin(result, dec, dec2, ctx, &status);
  379. return sq_Decimal_new_for_dec(v, result, ctx, status);
  380. }
  381. static SQRESULT sq_Decimal_next_minus(HSQUIRRELVM v)
  382. {
  383. SQ_FUNC_VARS_NO_TOP(v);
  384. GET_Decimal_INSTANCE(v, 1);
  385. mpd_context_t *ctx = sq_get_global_ctx(v, 1);
  386. mpd_t *result = mpd_new(ctx);
  387. uint32_t status = 0;
  388. mpd_qnext_minus(result, dec, ctx, &status);
  389. return sq_Decimal_new_for_dec(v, result, ctx, status);
  390. }
  391. static SQRESULT sq_Decimal_next_plus(HSQUIRRELVM v)
  392. {
  393. SQ_FUNC_VARS_NO_TOP(v);
  394. GET_Decimal_INSTANCE(v, 1);
  395. mpd_context_t *ctx = sq_get_global_ctx(v, 1);
  396. mpd_t *result = mpd_new(ctx);
  397. uint32_t status = 0;
  398. mpd_qnext_plus(result, dec, ctx, &status);
  399. return sq_Decimal_new_for_dec(v, result, ctx, status);
  400. }
  401. static SQRESULT sq_Decimal_next_toward(HSQUIRRELVM v)
  402. {
  403. SQ_FUNC_VARS_NO_TOP(v);
  404. GET_Decimal_INSTANCE(v, 1);
  405. GET_Decimal_INSTANCE2(v, 2);
  406. mpd_context_t *ctx = sq_get_global_ctx(v, 1);
  407. mpd_t *result = mpd_new(ctx);
  408. uint32_t status = 0;
  409. mpd_qnext_toward(result, dec, dec2, ctx, &status);
  410. return sq_Decimal_new_for_dec(v, result, ctx, status);
  411. }
  412. #define DECIMAL_IS(fn) \
  413. static SQRESULT sq_Decimal_##fn(HSQUIRRELVM v)\
  414. {\
  415. SQ_FUNC_VARS_NO_TOP(v);\
  416. GET_Decimal_INSTANCE(v, 1);\
  417. sq_pushbool(v, mpd_##fn(dec));\
  418. return 1;\
  419. }
  420. DECIMAL_IS(isfinite);
  421. DECIMAL_IS(isinfinite);
  422. DECIMAL_IS(isnan);
  423. DECIMAL_IS(isnegative);
  424. DECIMAL_IS(ispositive);
  425. DECIMAL_IS(isqnan);
  426. DECIMAL_IS(issigned);
  427. DECIMAL_IS(issnan);
  428. DECIMAL_IS(isspecial);
  429. DECIMAL_IS(iszero);
  430. DECIMAL_IS(isinteger);
  431. DECIMAL_IS(isodd);
  432. DECIMAL_IS(iseven);
  433. #define _DECL_FUNC(name,nparams,tycheck) {_SC(#name),sq_Decimal_##name,nparams,tycheck}
  434. static SQRegFunction Decimal_methods[] =
  435. {
  436. _DECL_FUNC(constructor,-1,_SC("x n|s|x")),
  437. _DECL_FUNC(set, 2,_SC("x n|s|x")),
  438. {_SC("_tostring"),sq_Decimal_tostring, 1,_SC("x")},
  439. _DECL_FUNC(tostring,1,_SC("x")),
  440. _DECL_FUNC(_add, 2,_SC("xx")),
  441. _DECL_FUNC(_sub, 2,_SC("xx")),
  442. _DECL_FUNC(_mul, 2,_SC("xx")),
  443. _DECL_FUNC(_div, 2,_SC("xx")),
  444. _DECL_FUNC(_modulo, 2,_SC("xx")),
  445. _DECL_FUNC(_unm, 1,_SC("x")),
  446. _DECL_FUNC(_cmp, 2,_SC("xx")),
  447. _DECL_FUNC(abs, 1,_SC("x")),
  448. _DECL_FUNC(max, 2,_SC("xx")),
  449. _DECL_FUNC(min, 2,_SC("xx")),
  450. _DECL_FUNC(next_minus, 1,_SC("x")),
  451. _DECL_FUNC(next_plus, 1,_SC("x")),
  452. _DECL_FUNC(next_toward, 2,_SC("xx")),
  453. _DECL_FUNC(isfinite, 1,_SC("x")),
  454. _DECL_FUNC(isinfinite, 1,_SC("x")),
  455. _DECL_FUNC(isnan, 1,_SC("x")),
  456. _DECL_FUNC(isnegative, 1,_SC("x")),
  457. _DECL_FUNC(ispositive, 1,_SC("x")),
  458. _DECL_FUNC(isqnan, 1,_SC("x")),
  459. _DECL_FUNC(issigned, 1,_SC("x")),
  460. _DECL_FUNC(issnan, 1,_SC("x")),
  461. _DECL_FUNC(isspecial, 1,_SC("x")),
  462. _DECL_FUNC(iszero, 1,_SC("x")),
  463. _DECL_FUNC(isinteger, 1,_SC("x")),
  464. _DECL_FUNC(isodd, 1,_SC("x")),
  465. _DECL_FUNC(iseven, 1,_SC("x")),
  466. {0,0}
  467. };
  468. #undef _DECL_FUNC
  469. #define CTXC(s) { _SC(#s), MPD_ ## s },
  470. static const struct {
  471. const SQChar* name;
  472. mpd_uint_t value;
  473. } ctx_constants[] = {
  474. /*Precision and Exponents*/
  475. CTXC(MAX_PREC)
  476. CTXC(MAX_EMAX)
  477. //CTXC(MIN_EMIN)
  478. /* rounding */
  479. CTXC(ROUND_UP) /* round away from 0 */
  480. CTXC(ROUND_DOWN) /* round toward 0 (truncate) */
  481. CTXC(ROUND_CEILING) /* round toward +infinity */
  482. CTXC(ROUND_FLOOR) /* round toward -infinity */
  483. CTXC(ROUND_HALF_UP) /* 0.5 is rounded up */
  484. CTXC(ROUND_HALF_DOWN) /* 0.5 is rounded down */
  485. CTXC(ROUND_HALF_EVEN) /* 0.5 is rounded to even */
  486. CTXC(ROUND_05UP) /* round zero or five away from 0 */
  487. CTXC(ROUND_TRUNC) /* truncate, but set infinities */
  488. /* Trap-enabler and Status flags */
  489. CTXC(Conversion_syntax)
  490. CTXC(Division_impossible)
  491. CTXC(Division_undefined)
  492. CTXC(Invalid_context)
  493. CTXC(Invalid_operation)
  494. CTXC(Malloc_error)
  495. CTXC(Clamped)
  496. CTXC(Division_by_zero)
  497. CTXC(Fpu_error)
  498. CTXC(Inexact)
  499. CTXC(Not_implemented)
  500. CTXC(Overflow)
  501. CTXC(Rounded)
  502. CTXC(Subnormal)
  503. CTXC(Underflow)
  504. CTXC(IEEE_Invalid_operation)
  505. /*IEEE Interchange Formats*/
  506. CTXC(IEEE_CONTEXT_MAX_BITS)
  507. CTXC(DECIMAL32)
  508. CTXC(DECIMAL64)
  509. CTXC(DECIMAL128)
  510. /* terminator */
  511. { NULL, 0 }
  512. };
  513. #ifdef __cplusplus
  514. extern "C" {
  515. #endif
  516. SQRESULT sqext_register_decimal(HSQUIRRELVM v)
  517. {
  518. SQ_PUSH_DECIMAL_CTX_TAG(v);
  519. sq_newclass(v,SQFalse);
  520. sq_settypetag(v,-1,(void*)sq_decimal_ctx_TAG);
  521. sq_insert_reg_funcs(v, DecimalCtx_methods);
  522. for(int i=0; ctx_constants[i].name; ++i){
  523. sq_pushstring(v, ctx_constants[i].name, -1);
  524. sq_pushinteger(v, ctx_constants[i].value);
  525. sq_newslot(v,-3,SQTrue);
  526. }
  527. sq_newslot(v,-3,SQTrue);
  528. SQ_PUSH_DECIMAL_TAG(v);
  529. sq_newclass(v,SQFalse);
  530. sq_settypetag(v,-1,(void*)sq_decimal_TAG);
  531. SQ_PUSH_CONTEXT_STATIC(v);
  532. sq_pushstring(v,sq_decimal_ctx_TAG,-1);
  533. sq_getonroottable(v);
  534. sq_pushroottable(v);
  535. sq_call(v, 1, SQTrue, SQFalse);
  536. sq_remove(v, -2);
  537. sq_newslot(v,-3,SQTrue);
  538. sq_insert_reg_funcs(v, Decimal_methods);
  539. sq_newslot(v,-3,SQTrue);
  540. return 0;
  541. }
  542. #ifdef __cplusplus
  543. }
  544. #endif