PageRenderTime 47ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 1ms

/src/builtin_arithmetic.cpp

https://github.com/mrpg/valency
C++ | 321 lines | 274 code | 34 blank | 13 comment | 152 complexity | 03dfb803c0b6ea11b75feffbd0fd32f2 MD5 | raw file
Possible License(s): WTFPL
  1. /* Valency 0.2
  2. * 2012, Max R. P. Grossmann
  3. *
  4. * This program is free software. It comes without any warranty, to
  5. * the extent permitted by applicable law. You can redistribute it
  6. * and/or modify it under the terms of the Do What The Fuck You Want
  7. * To Public License, Version 2, as published by Sam Hocevar. See
  8. * http://sam.zoy.org/wtfpl/COPYING for more details. */
  9. inline bool all_of_type(vector<shared_ptr<instr_t>>& arg, var_type type) {
  10. size_t i = 0, m = arg.size()-1;
  11. for (auto& cur: arg) {
  12. if (i != 0 && i != m) {
  13. if (cur->type != type) {
  14. return false;
  15. }
  16. }
  17. i++;
  18. }
  19. return true;
  20. }
  21. inline double getdouble(shared_ptr<instr_t>& x) {
  22. if (x->type == XFLOATT) {
  23. return *((double*)x->p);
  24. }
  25. else if (x->type == XNUMT) {
  26. return (double)(*((int64_t*)x->p));
  27. }
  28. else {
  29. return 0.0;
  30. }
  31. }
  32. inline double getdouble(shared_ptr<instr_t>& x, double onfail) {
  33. if (x->type == XFLOATT) {
  34. return *((double*)x->p);
  35. }
  36. else if (x->type == XNUMT) {
  37. return (double)(*((int64_t*)x->p));
  38. }
  39. else {
  40. return onfail;
  41. }
  42. }
  43. inline int64_t getint(shared_ptr<instr_t>& x) {
  44. if (x->type == XFLOATT) {
  45. return (int64_t)(*((double*)x->p));
  46. }
  47. else if (x->type == XNUMT) {
  48. return (*((int64_t*)x->p));
  49. }
  50. else {
  51. return 0;
  52. }
  53. }
  54. inline bool isnumeric(const var_type& a) {
  55. return (a == XNUMT || a == XFLOATT);
  56. }
  57. inline var_type biggest_range(vector<shared_ptr<instr_t>>& arg) {
  58. size_t i = 0, m = arg.size()-1;
  59. var_type r = XNULLT;
  60. for (auto& cur: arg) {
  61. if (i != 0 && i != m) {
  62. if (cur->type == XFLOATT) {
  63. r = XFLOATT;
  64. }
  65. else if (cur->type == XSTRINGT) {
  66. return XSTRINGT;
  67. }
  68. else if (cur->type == XNUMT && r != XFLOATT) {
  69. r = XNUMT;
  70. }
  71. }
  72. i++;
  73. }
  74. return r;
  75. }
  76. void builtin_mul(vector<shared_ptr<instr_t>>& arg) {
  77. if (arg.size() >= 4) {
  78. size_t m = arg.size()-1;
  79. //~ gc_handler(arg[m]);
  80. arg[m]->type = biggest_range(arg);
  81. size_t i = 0;
  82. if (arg[m]->type == XFLOATT) {
  83. arg[m]->p = new double(1);
  84. double* p = (double*)arg[m]->p;
  85. for (auto& cur: arg) {
  86. if (i != m && i != 0) {
  87. *p *= getdouble(cur);
  88. }
  89. i++;
  90. }
  91. }
  92. else if (arg[m]->type == XNUMT) {
  93. arg[m]->p = new int64_t(1);
  94. int64_t* p = (int64_t*)arg[m]->p;
  95. for (auto& cur: arg) {
  96. if (i != m && i != 0) {
  97. *p *= getint(cur);
  98. }
  99. i++;
  100. }
  101. }
  102. else {
  103. cerr << "Fatal, Aborting: Wrong types for `mul'." << endl;
  104. halt(28);
  105. }
  106. }
  107. else {
  108. cerr << "Fatal, Aborting: `mul' needs at least 3 arguments (" << arg.size()-1 << " given)." << endl;
  109. halt(34);
  110. }
  111. }
  112. void builtin_gamma(vector<shared_ptr<instr_t>>& arg) {
  113. if (arg.size() == 3) {
  114. if (isnumeric(arg[1]->type)) {
  115. arg[2]->type = XFLOATT;
  116. arg[2]->p = new double(tgamma(getdouble(arg[1])));
  117. }
  118. else {
  119. cerr << "Fatal, Aborting: Wrong types for `gamma'." << endl;
  120. halt(28);
  121. }
  122. }
  123. else {
  124. cerr << "Fatal, Aborting: `gamma' needs exactly 2 arguments (" << arg.size()-1 << " given)." << endl;
  125. halt(34);
  126. }
  127. }
  128. void builtin_factorial(vector<shared_ptr<instr_t>>& arg) {
  129. if (arg.size() == 3) {
  130. if (isnumeric(arg[1]->type)) {
  131. int64_t x = getint(arg[1]);
  132. double r = 1;
  133. while (x > 0) {
  134. r *= x;
  135. x--;
  136. }
  137. arg[2]->type = XFLOATT;
  138. arg[2]->p = new double(r);
  139. }
  140. else {
  141. cerr << "Fatal, Aborting: Wrong types for `factorial'." << endl;
  142. halt(28);
  143. }
  144. }
  145. else {
  146. cerr << "Fatal, Aborting: `factorial' needs exactly 2 arguments (" << arg.size()-1 << " given)." << endl;
  147. halt(34);
  148. }
  149. }
  150. void builtin_add(vector<shared_ptr<instr_t>>& arg) {
  151. if (arg.size() >= 4) {
  152. size_t m = arg.size()-1;
  153. //~ gc_handler(arg[m]);
  154. arg[m]->type = biggest_range(arg);
  155. size_t i = 0;
  156. if (arg[m]->type == XFLOATT) {
  157. arg[m]->p = new double(0);
  158. double* p = (double*)arg[m]->p;
  159. for (auto& cur: arg) {
  160. if (i != m && i != 0) {
  161. *p += getdouble(cur);
  162. }
  163. i++;
  164. }
  165. }
  166. else if (arg[m]->type == XNUMT) {
  167. arg[m]->p = new int64_t(0);
  168. int64_t* p = (int64_t*)arg[m]->p;
  169. for (auto& cur: arg) {
  170. if (i != m && i != 0) {
  171. *p += getint(cur);
  172. }
  173. i++;
  174. }
  175. }
  176. else if (arg[m]->type == XSTRINGT && all_of_type(arg,XSTRINGT)) {
  177. arg[m]->p = new string;
  178. string* p = (string*)arg[m]->p;
  179. for (auto& cur: arg) {
  180. if (i != m && i != 0) {
  181. *p += *((string*)cur->p);
  182. }
  183. i++;
  184. }
  185. }
  186. else {
  187. cerr << "Fatal, Aborting: Wrong types for `add'." << endl;
  188. halt(28);
  189. }
  190. }
  191. else {
  192. cerr << "Fatal, Aborting: `add' needs at least 3 arguments (" << arg.size()-1 << " given)." << endl;
  193. halt(34);
  194. }
  195. }
  196. void builtin_sub(vector<shared_ptr<instr_t>>& arg) {
  197. if (arg.size() >= 4) {
  198. size_t m = arg.size()-1;
  199. //~ gc_handler(arg[m]);
  200. arg[m]->type = biggest_range(arg);
  201. size_t i = 0;
  202. if (arg[m]->type == XFLOATT) {
  203. arg[m]->p = new double(getdouble(arg[1]));
  204. double* p = (double*)arg[m]->p;
  205. for (auto& cur: arg) {
  206. if (i != m && i != 0 && i != 1) {
  207. *p -= getdouble(cur);
  208. }
  209. i++;
  210. }
  211. }
  212. else if (arg[m]->type == XNUMT) {
  213. arg[m]->p = new int64_t(getint(arg[1]));
  214. int64_t* p = (int64_t*)arg[m]->p;
  215. for (auto& cur: arg) {
  216. if (i != m && i != 0 && i != 1) {
  217. *p -= getint(cur);
  218. }
  219. i++;
  220. }
  221. }
  222. else {
  223. cerr << "Fatal, Aborting: Wrong types for `sub'." << endl;
  224. halt(28);
  225. }
  226. }
  227. else {
  228. cerr << "Fatal, Aborting: `sub' needs at least 3 arguments (" << arg.size()-1 << " given)." << endl;
  229. halt(34);
  230. }
  231. }
  232. void builtin_div(vector<shared_ptr<instr_t>>& arg) {
  233. if (arg.size() >= 4) {
  234. size_t m = arg.size()-1;
  235. //~ gc_handler(arg[m]);
  236. arg[m]->type = XFLOATT;
  237. size_t i = 0;
  238. arg[m]->p = new double(getdouble(arg[1]));
  239. double* p = (double*)arg[m]->p;
  240. for (auto& cur: arg) {
  241. if (i != m && i != 0 && i != 1) {
  242. *p /= getdouble(cur,1);
  243. }
  244. i++;
  245. }
  246. }
  247. else {
  248. cerr << "Fatal, Aborting: `div' needs at least 3 arguments (" << arg.size()-1 << " given)." << endl;
  249. halt(34);
  250. }
  251. }
  252. void builtin_mod(vector<shared_ptr<instr_t>>& arg) {
  253. if (arg.size() >= 4) {
  254. size_t m = arg.size()-1;
  255. //~ gc_handler(arg[m]);
  256. arg[m]->type = biggest_range(arg);
  257. size_t i = 0;
  258. if (arg[m]->type == XFLOATT) {
  259. arg[m]->p = new double(getdouble(arg[1]));
  260. double* p = (double*)arg[m]->p;
  261. for (auto& cur: arg) {
  262. if (i != m && i != 0 && i != 1) {
  263. *p = fmod(*p,getdouble(cur));
  264. }
  265. i++;
  266. }
  267. }
  268. else if (arg[m]->type == XNUMT) {
  269. arg[m]->p = new int64_t(getint(arg[1]));
  270. int64_t* p = (int64_t*)arg[m]->p;
  271. for (auto& cur: arg) {
  272. if (i != m && i != 0 && i != 1) {
  273. *p %= getint(cur);
  274. }
  275. i++;
  276. }
  277. }
  278. else {
  279. cerr << "Fatal, Aborting: Wrong types for `mod'." << endl;
  280. halt(28);
  281. }
  282. }
  283. else {
  284. cerr << "Fatal, Aborting: `mod' needs at least 3 arguments (" << arg.size()-1 << " given)." << endl;
  285. halt(34);
  286. }
  287. }