sq_decimal.cpp 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607
  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. #ifdef CONFIG_32
  194. mpd_qset_i32(dec, iparam, ctx, status);
  195. #else
  196. mpd_qset_i64(dec, iparam, ctx, status);
  197. #endif
  198. }
  199. break;
  200. case OT_STRING:{
  201. SQ_GET_STRING(v, idx, str);
  202. mpd_qset_string(dec, str, ctx, status);
  203. }
  204. break;
  205. case OT_FLOAT:{
  206. SQ_GET_FLOAT(v, idx, fparam);
  207. char buf[32];
  208. snprintf(buf, sizeof(buf), "%f", fparam);
  209. mpd_qset_string(dec, buf, ctx, status);
  210. }
  211. break;
  212. default:
  213. return sq_throwerror(v, _SC("invalid type (%s) to convert to decimal"), sq_gettypename(v, idx));
  214. }
  215. return SQ_OK;
  216. }
  217. static SQRESULT sq_Decimal_release_hook(SQUserPointer p, SQInteger size, void */*ep*/) {
  218. mpd_t *dec = (mpd_t *)p;
  219. if(dec) mpd_del(dec);
  220. return 0;
  221. }
  222. /*
  223. ** Creates a new Decimal.
  224. */
  225. static SQRESULT sq_Decimal_constructor (HSQUIRRELVM v) {
  226. uint32_t status = 0;
  227. mpd_context_t *ctx = sq_get_global_ctx(v, 1);
  228. mpd_t *dec = mpd_new(ctx);
  229. if(sq_gettop(v) > 1){
  230. if(sq_Decimal_set_from(v, 2, ctx, dec, &status) != SQ_OK) return SQ_ERROR;
  231. }
  232. else
  233. #ifdef CONFIG_32
  234. mpd_qset_i32(dec, 0, ctx, &status);
  235. #else
  236. mpd_qset_i64(dec, 0, ctx, &status);
  237. #endif
  238. ctx->status |= status;
  239. if (status&ctx->traps) {
  240. mpd_del(dec);
  241. return sq_Decimal_error(v, status);
  242. }
  243. sq_setinstanceup(v, 1, dec);
  244. sq_setreleasehook(v, 1, sq_Decimal_release_hook);
  245. return 1;
  246. }
  247. static SQRESULT sq_Decimal_set(HSQUIRRELVM v)
  248. {
  249. SQ_FUNC_VARS_NO_TOP(v);
  250. GET_Decimal_INSTANCE(v, 1);
  251. uint32_t status = 0;
  252. mpd_context_t *ctx = sq_get_global_ctx(v, 1);
  253. if(sq_Decimal_set_from(v, 2, ctx, dec, &status) != SQ_OK) return SQ_ERROR;
  254. ctx->status |= status;
  255. if (status&ctx->traps) {
  256. return sq_Decimal_error(v, status);
  257. }
  258. sq_settop(v, 1); //returns itself
  259. return 1;
  260. }
  261. static SQRESULT sq_Decimal_new_for_dec (HSQUIRRELVM v, mpd_t *dec, mpd_context_t *ctx, uint32_t status) {
  262. //mpd_addstatus_raise(ctx, status);
  263. ctx->status |= status;
  264. if (status&ctx->traps) {
  265. mpd_del(dec);
  266. return sq_Decimal_error(v, status);
  267. }
  268. sq_pushstring(v, sq_decimal_TAG, -1);
  269. sq_getonroottable(v);
  270. sq_createinstance(v, -1);
  271. sq_setinstanceup(v, -1, dec);
  272. sq_setreleasehook(v, -1, sq_Decimal_release_hook);
  273. return 1;
  274. }
  275. static SQRESULT sq_Decimal_tostring(HSQUIRRELVM v)
  276. {
  277. SQ_FUNC_VARS_NO_TOP(v);
  278. GET_Decimal_INSTANCE(v, 1);
  279. char *decstring = mpd_to_eng(dec, 1);
  280. sq_pushstring(v, decstring, -1);
  281. if (decstring) mpd_free(decstring);
  282. return 1;
  283. }
  284. static SQRESULT sq_Decimal__add(HSQUIRRELVM v)
  285. {
  286. SQ_FUNC_VARS_NO_TOP(v);
  287. GET_Decimal_INSTANCE(v, 1);
  288. GET_Decimal_INSTANCE2(v, 2);
  289. mpd_context_t *ctx = sq_get_global_ctx(v, 1);
  290. mpd_t *result = mpd_new(ctx);
  291. uint32_t status = 0;
  292. mpd_qadd(result, dec, dec2, ctx, &status);
  293. return sq_Decimal_new_for_dec(v, result, ctx, status);
  294. }
  295. static SQRESULT sq_Decimal__sub(HSQUIRRELVM v)
  296. {
  297. SQ_FUNC_VARS_NO_TOP(v);
  298. GET_Decimal_INSTANCE(v, 1);
  299. GET_Decimal_INSTANCE2(v, 2);
  300. mpd_context_t *ctx = sq_get_global_ctx(v, 1);
  301. mpd_t *result = mpd_new(ctx);
  302. uint32_t status = 0;
  303. mpd_qsub(result, dec, dec2, ctx, &status);
  304. return sq_Decimal_new_for_dec(v, result, ctx, status);
  305. }
  306. static SQRESULT sq_Decimal__mul(HSQUIRRELVM v)
  307. {
  308. SQ_FUNC_VARS_NO_TOP(v);
  309. GET_Decimal_INSTANCE(v, 1);
  310. GET_Decimal_INSTANCE2(v, 2);
  311. mpd_context_t *ctx = sq_get_global_ctx(v, 1);
  312. mpd_t *result = mpd_new(ctx);
  313. uint32_t status = 0;
  314. mpd_qmul(result, dec, dec2, ctx, &status);
  315. return sq_Decimal_new_for_dec(v, result, ctx, status);
  316. }
  317. static SQRESULT sq_Decimal__div(HSQUIRRELVM v)
  318. {
  319. SQ_FUNC_VARS_NO_TOP(v);
  320. GET_Decimal_INSTANCE(v, 1);
  321. GET_Decimal_INSTANCE2(v, 2);
  322. mpd_context_t *ctx = sq_get_global_ctx(v, 1);
  323. mpd_t *result = mpd_new(ctx);
  324. uint32_t status = 0;
  325. mpd_qdiv(result, dec, dec2, ctx, &status);
  326. return sq_Decimal_new_for_dec(v, result, ctx, status);
  327. }
  328. static SQRESULT sq_Decimal__modulo(HSQUIRRELVM v)
  329. {
  330. SQ_FUNC_VARS_NO_TOP(v);
  331. GET_Decimal_INSTANCE(v, 1);
  332. GET_Decimal_INSTANCE2(v, 2);
  333. mpd_context_t *ctx = sq_get_global_ctx(v, 1);
  334. mpd_t *result = mpd_new(ctx);
  335. uint32_t status = 0;
  336. mpd_qrem(result, dec, dec2, ctx, &status);
  337. return sq_Decimal_new_for_dec(v, result, ctx, status);
  338. }
  339. static SQRESULT sq_Decimal__unm(HSQUIRRELVM v)
  340. {
  341. SQ_FUNC_VARS_NO_TOP(v);
  342. GET_Decimal_INSTANCE(v, 1);
  343. mpd_context_t *ctx = sq_get_global_ctx(v, 1);
  344. mpd_t *result = mpd_new(ctx);
  345. uint32_t status = 0;
  346. mpd_qminus(result, dec, ctx, &status);
  347. return sq_Decimal_new_for_dec(v, result, ctx, status);
  348. }
  349. static SQRESULT sq_Decimal__cmp(HSQUIRRELVM v)
  350. {
  351. SQ_FUNC_VARS_NO_TOP(v);
  352. GET_Decimal_INSTANCE(v, 1);
  353. GET_Decimal_INSTANCE2(v, 2);
  354. mpd_context_t *ctx = sq_get_global_ctx(v, 1);
  355. sq_pushinteger(v, mpd_cmp(dec, dec2, ctx));
  356. return 1;
  357. }
  358. static SQRESULT sq_Decimal_abs(HSQUIRRELVM v)
  359. {
  360. SQ_FUNC_VARS_NO_TOP(v);
  361. GET_Decimal_INSTANCE(v, 1);
  362. mpd_context_t *ctx = sq_get_global_ctx(v, 1);
  363. mpd_t *result = mpd_new(ctx);
  364. uint32_t status = 0;
  365. mpd_qabs(result, dec, ctx, &status);
  366. return sq_Decimal_new_for_dec(v, result, ctx, status);
  367. }
  368. static SQRESULT sq_Decimal_max(HSQUIRRELVM v)
  369. {
  370. SQ_FUNC_VARS_NO_TOP(v);
  371. GET_Decimal_INSTANCE(v, 1);
  372. GET_Decimal_INSTANCE2(v, 2);
  373. mpd_context_t *ctx = sq_get_global_ctx(v, 1);
  374. mpd_t *result = mpd_new(ctx);
  375. uint32_t status = 0;
  376. mpd_qmax(result, dec, dec2, ctx, &status);
  377. return sq_Decimal_new_for_dec(v, result, ctx, status);
  378. }
  379. static SQRESULT sq_Decimal_min(HSQUIRRELVM v)
  380. {
  381. SQ_FUNC_VARS_NO_TOP(v);
  382. GET_Decimal_INSTANCE(v, 1);
  383. GET_Decimal_INSTANCE2(v, 2);
  384. mpd_context_t *ctx = sq_get_global_ctx(v, 1);
  385. mpd_t *result = mpd_new(ctx);
  386. uint32_t status = 0;
  387. mpd_qmin(result, dec, dec2, ctx, &status);
  388. return sq_Decimal_new_for_dec(v, result, ctx, status);
  389. }
  390. static SQRESULT sq_Decimal_next_minus(HSQUIRRELVM v)
  391. {
  392. SQ_FUNC_VARS_NO_TOP(v);
  393. GET_Decimal_INSTANCE(v, 1);
  394. mpd_context_t *ctx = sq_get_global_ctx(v, 1);
  395. mpd_t *result = mpd_new(ctx);
  396. uint32_t status = 0;
  397. mpd_qnext_minus(result, dec, ctx, &status);
  398. return sq_Decimal_new_for_dec(v, result, ctx, status);
  399. }
  400. static SQRESULT sq_Decimal_next_plus(HSQUIRRELVM v)
  401. {
  402. SQ_FUNC_VARS_NO_TOP(v);
  403. GET_Decimal_INSTANCE(v, 1);
  404. mpd_context_t *ctx = sq_get_global_ctx(v, 1);
  405. mpd_t *result = mpd_new(ctx);
  406. uint32_t status = 0;
  407. mpd_qnext_plus(result, dec, ctx, &status);
  408. return sq_Decimal_new_for_dec(v, result, ctx, status);
  409. }
  410. static SQRESULT sq_Decimal_next_toward(HSQUIRRELVM v)
  411. {
  412. SQ_FUNC_VARS_NO_TOP(v);
  413. GET_Decimal_INSTANCE(v, 1);
  414. GET_Decimal_INSTANCE2(v, 2);
  415. mpd_context_t *ctx = sq_get_global_ctx(v, 1);
  416. mpd_t *result = mpd_new(ctx);
  417. uint32_t status = 0;
  418. mpd_qnext_toward(result, dec, dec2, ctx, &status);
  419. return sq_Decimal_new_for_dec(v, result, ctx, status);
  420. }
  421. #define DECIMAL_IS(fn) \
  422. static SQRESULT sq_Decimal_##fn(HSQUIRRELVM v)\
  423. {\
  424. SQ_FUNC_VARS_NO_TOP(v);\
  425. GET_Decimal_INSTANCE(v, 1);\
  426. sq_pushbool(v, mpd_##fn(dec));\
  427. return 1;\
  428. }
  429. DECIMAL_IS(isfinite);
  430. DECIMAL_IS(isinfinite);
  431. DECIMAL_IS(isnan);
  432. DECIMAL_IS(isnegative);
  433. DECIMAL_IS(ispositive);
  434. DECIMAL_IS(isqnan);
  435. DECIMAL_IS(issigned);
  436. DECIMAL_IS(issnan);
  437. DECIMAL_IS(isspecial);
  438. DECIMAL_IS(iszero);
  439. DECIMAL_IS(isinteger);
  440. DECIMAL_IS(isodd);
  441. DECIMAL_IS(iseven);
  442. #define _DECL_FUNC(name,nparams,tycheck) {_SC(#name),sq_Decimal_##name,nparams,tycheck}
  443. static SQRegFunction Decimal_methods[] =
  444. {
  445. _DECL_FUNC(constructor,-1,_SC("x n|s|x")),
  446. _DECL_FUNC(set, 2,_SC("x n|s|x")),
  447. {_SC("_tostring"),sq_Decimal_tostring, 1,_SC("x")},
  448. _DECL_FUNC(tostring,1,_SC("x")),
  449. _DECL_FUNC(_add, 2,_SC("xx")),
  450. _DECL_FUNC(_sub, 2,_SC("xx")),
  451. _DECL_FUNC(_mul, 2,_SC("xx")),
  452. _DECL_FUNC(_div, 2,_SC("xx")),
  453. _DECL_FUNC(_modulo, 2,_SC("xx")),
  454. _DECL_FUNC(_unm, 1,_SC("x")),
  455. _DECL_FUNC(_cmp, 2,_SC("xx")),
  456. _DECL_FUNC(abs, 1,_SC("x")),
  457. _DECL_FUNC(max, 2,_SC("xx")),
  458. _DECL_FUNC(min, 2,_SC("xx")),
  459. _DECL_FUNC(next_minus, 1,_SC("x")),
  460. _DECL_FUNC(next_plus, 1,_SC("x")),
  461. _DECL_FUNC(next_toward, 2,_SC("xx")),
  462. _DECL_FUNC(isfinite, 1,_SC("x")),
  463. _DECL_FUNC(isinfinite, 1,_SC("x")),
  464. _DECL_FUNC(isnan, 1,_SC("x")),
  465. _DECL_FUNC(isnegative, 1,_SC("x")),
  466. _DECL_FUNC(ispositive, 1,_SC("x")),
  467. _DECL_FUNC(isqnan, 1,_SC("x")),
  468. _DECL_FUNC(issigned, 1,_SC("x")),
  469. _DECL_FUNC(issnan, 1,_SC("x")),
  470. _DECL_FUNC(isspecial, 1,_SC("x")),
  471. _DECL_FUNC(iszero, 1,_SC("x")),
  472. _DECL_FUNC(isinteger, 1,_SC("x")),
  473. _DECL_FUNC(isodd, 1,_SC("x")),
  474. _DECL_FUNC(iseven, 1,_SC("x")),
  475. {0,0}
  476. };
  477. #undef _DECL_FUNC
  478. #define CTXC(s) { _SC(#s), MPD_ ## s },
  479. static const struct {
  480. const SQChar* name;
  481. mpd_uint_t value;
  482. } ctx_constants[] = {
  483. /*Precision and Exponents*/
  484. CTXC(MAX_PREC)
  485. CTXC(MAX_EMAX)
  486. //CTXC(MIN_EMIN)
  487. /* rounding */
  488. CTXC(ROUND_UP) /* round away from 0 */
  489. CTXC(ROUND_DOWN) /* round toward 0 (truncate) */
  490. CTXC(ROUND_CEILING) /* round toward +infinity */
  491. CTXC(ROUND_FLOOR) /* round toward -infinity */
  492. CTXC(ROUND_HALF_UP) /* 0.5 is rounded up */
  493. CTXC(ROUND_HALF_DOWN) /* 0.5 is rounded down */
  494. CTXC(ROUND_HALF_EVEN) /* 0.5 is rounded to even */
  495. CTXC(ROUND_05UP) /* round zero or five away from 0 */
  496. CTXC(ROUND_TRUNC) /* truncate, but set infinities */
  497. /* Trap-enabler and Status flags */
  498. CTXC(Conversion_syntax)
  499. CTXC(Division_impossible)
  500. CTXC(Division_undefined)
  501. CTXC(Invalid_context)
  502. CTXC(Invalid_operation)
  503. CTXC(Malloc_error)
  504. CTXC(Clamped)
  505. CTXC(Division_by_zero)
  506. CTXC(Fpu_error)
  507. CTXC(Inexact)
  508. CTXC(Not_implemented)
  509. CTXC(Overflow)
  510. CTXC(Rounded)
  511. CTXC(Subnormal)
  512. CTXC(Underflow)
  513. CTXC(IEEE_Invalid_operation)
  514. /*IEEE Interchange Formats*/
  515. CTXC(IEEE_CONTEXT_MAX_BITS)
  516. CTXC(DECIMAL32)
  517. CTXC(DECIMAL64)
  518. CTXC(DECIMAL128)
  519. /* terminator */
  520. { NULL, 0 }
  521. };
  522. #ifdef __cplusplus
  523. extern "C" {
  524. #endif
  525. SQRESULT sqext_register_decimal(HSQUIRRELVM v)
  526. {
  527. SQ_PUSH_DECIMAL_CTX_TAG(v);
  528. sq_newclass(v,SQFalse);
  529. sq_settypetag(v,-1,(void*)sq_decimal_ctx_TAG);
  530. sq_insert_reg_funcs(v, DecimalCtx_methods);
  531. for(int i=0; ctx_constants[i].name; ++i){
  532. sq_pushstring(v, ctx_constants[i].name, -1);
  533. sq_pushinteger(v, ctx_constants[i].value);
  534. sq_newslot(v,-3,SQTrue);
  535. }
  536. sq_newslot(v,-3,SQTrue);
  537. SQ_PUSH_DECIMAL_TAG(v);
  538. sq_newclass(v,SQFalse);
  539. sq_settypetag(v,-1,(void*)sq_decimal_TAG);
  540. SQ_PUSH_CONTEXT_STATIC(v);
  541. sq_pushstring(v,sq_decimal_ctx_TAG,-1);
  542. sq_getonroottable(v);
  543. sq_pushroottable(v);
  544. sq_call(v, 1, SQTrue, SQFalse);
  545. sq_remove(v, -2);
  546. sq_newslot(v,-3,SQTrue);
  547. sq_insert_reg_funcs(v, Decimal_methods);
  548. sq_newslot(v,-3,SQTrue);
  549. return 0;
  550. }
  551. #ifdef __cplusplus
  552. }
  553. #endif