INT.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450
  1. // C source file with functions to deal with integers
  2. /***********************************************************
  3. * functions to print the value of bean primite integer types
  4. ************************************************************/
  5. // print_byte_num() function
  6. umax print_byte_num(void * ptr, umax size) {
  7. if (size < 1)
  8. return 0;
  9. printf("%u", *((byte *) ptr));
  10. return size;
  11. }
  12. // print_byte_hex() function
  13. umax print_byte_hex(void * ptr, umax size) {
  14. if (size < 1)
  15. return 0;
  16. printf("%02X", *((byte *) ptr));
  17. return size;
  18. }
  19. // print_char_num() function
  20. umax print_char_num(void * ptr, umax size) {
  21. if (size < 1)
  22. return 0;
  23. printf("%d", *((char *) ptr));
  24. return size;
  25. }
  26. // print_umax_num() function
  27. umax print_umax_num(void * ptr, umax size) {
  28. if (size < sizeof(umax))
  29. return 0;
  30. printf("%llu", *((umax *) ptr));
  31. return size;
  32. }
  33. // print_umax_hex() function
  34. umax print_umax_hex(void * ptr, umax size) {
  35. if (size < sizeof(umax))
  36. return 0;
  37. printf("%08llX", *((umax *) ptr));
  38. return size;
  39. }
  40. // print_smax_num() function
  41. umax print_smax_num(void * ptr, umax size) {
  42. if (size < sizeof(smax))
  43. return 0;
  44. printf("%lld", *((smax *) ptr));
  45. return size;
  46. }
  47. /***********************************************
  48. * powerof functions for signed/unsigned integers
  49. ************************************************/
  50. // powerof_uint() function
  51. // function to calculate the power of an unsigned integer to an unsigned
  52. // exponent (an unsigned integer that is limited to umax container)
  53. umax powerof_uint(umax base, byte exponent)
  54. {
  55. // base equals 0
  56. if (base == 0)
  57. return 0;
  58. // exponent equals 0
  59. if (exponent == 0)
  60. return 1;
  61. // otherwise, calculate (base ^ (exponent))
  62. umax result = base;
  63. for (umax i = 2; i <= exponent; i++)
  64. result *= base;
  65. return result;
  66. }
  67. // powerof_sint() function
  68. // function to calculate the power of a signed integer to an unsigned
  69. // exponent (a signed integer limited to smax container)
  70. smax powerof_sint(smax base, byte exponent)
  71. {
  72. // base equals 0
  73. if (base == 0)
  74. return 0;
  75. // exponent equals 0
  76. if (exponent == 0)
  77. return 1;
  78. // calculate result
  79. smax result = 1;
  80. for (umax i = 1; i <= exponent; i++)
  81. result *= base;
  82. return result;
  83. }
  84. // get_max_uint() function
  85. // return the maximum of 2 umaxs
  86. umax get_max_uint(umax uint_1, umax uint_2)
  87. {
  88. return uint_1 > uint_2 ? uint_1 : uint_2;
  89. }
  90. // get_min_uint() function
  91. // return the minimum of 2 umaxs
  92. umax get_min_uint(umax uint_1, umax uint_2)
  93. {
  94. return uint_1 > uint_2 ? uint_2 : uint_1;
  95. }
  96. /********************************************************************************
  97. * functions to calculate some types of integers from bits in the BIT_HOLDER array
  98. *********************************************************************************/
  99. /*********
  100. * UNSIGNED
  101. * Example: 10011101 (binary, 8 bits long)
  102. * 1*(2)^7 + 0*(2)^6 + 0*(2)^5 + 1*(2)^4 + 1*(2)^3 + 1*(2)^2 + 0*(2)^1 + 1*(2)^0 = 157 (decimal)
  103. ***********************************************************************************************/
  104. // bits_to_std_uint() function
  105. // function to calculate an unsigned integer using the standard
  106. // calculation method. It will read the bits on the BIT_HOLDER array
  107. // (overflow will occur if the integer calculated goes outside umax!)
  108. umax bits_to_std_uint(umax bit_holder_pos)
  109. {
  110. umax result = 0;
  111. umax int_bit_size = BIT_HOLDER_LENGTH - bit_holder_pos;
  112. for (umax i = 0; i < int_bit_size; i++)
  113. result += BIT_HOLDER[BIT_HOLDER_LENGTH - i - 1] * powerof_uint(2, i);
  114. return result;
  115. }
  116. // tbh idk about another unsigned representation, if you do, let me know
  117. /*******
  118. * SIGNED
  119. * Info about each representation here
  120. * https://en.wikipedia.org/wiki/Signed_number_representations
  121. *************************************************************/
  122. // bits_to_sign_mag_sint() function
  123. // treat the n-1 bits to the right of the binary number as an unsigned integer
  124. // then add the sign from the leftmost bit to the left (1 = minus, 0 = plus)
  125. smax bits_to_sign_mag_sint(umax bit_holder_pos)
  126. {
  127. smax result = 0;
  128. umax int_bit_size = BIT_HOLDER_LENGTH - bit_holder_pos;
  129. // get the magnitude of the number
  130. for (umax i = 0; i < int_bit_size - 1; i++)
  131. result += BIT_HOLDER[BIT_HOLDER_LENGTH - i - 1] * powerof_uint(2, i);
  132. // get the sign
  133. result *= BIT_HOLDER[BIT_HOLDER_LENGTH - int_bit_size] == 1 ? -1 : 1;
  134. return result;
  135. }
  136. // bits_to_1_compl_sint() function
  137. // is like 2's compl but with a twist (what a description by me)
  138. smax bits_to_1_compl_sint(umax bit_holder_pos)
  139. {
  140. smax result = 0;
  141. umax int_bit_size = BIT_HOLDER_LENGTH - bit_holder_pos;
  142. // get the substraction done already
  143. if (BIT_HOLDER[BIT_HOLDER_LENGTH - int_bit_size] == 1)
  144. result -= 1 * powerof_uint(2, int_bit_size - 1) - 1;
  145. // calculate the rest of the number as an unsigned int
  146. for (umax i = 0; i < int_bit_size - 1; i++)
  147. result += BIT_HOLDER[BIT_HOLDER_LENGTH - i - 1] * powerof_uint(2, i);
  148. return result;
  149. }
  150. // bits_to_2_compl_sint() function
  151. // the one that is used on most systems from today
  152. smax bits_to_2_compl_sint(umax bit_holder_pos)
  153. {
  154. smax result = 0;
  155. umax int_bit_size = BIT_HOLDER_LENGTH - bit_holder_pos;
  156. // get the substraction done already
  157. if (BIT_HOLDER[BIT_HOLDER_LENGTH - int_bit_size] == 1)
  158. result -= 1 * powerof_uint(2, int_bit_size - 1);
  159. // get the rest of the number as an unsigned integer and add it to result
  160. for (umax i = 0; i < int_bit_size - 1; i++)
  161. result += BIT_HOLDER[BIT_HOLDER_LENGTH - i - 1] * powerof_uint(2, i);
  162. return result;
  163. }
  164. // bits_to_off_bin_sint() function
  165. // 0 is just placed at the 1000....0000 binary number
  166. smax bits_to_off_bin_sint(umax bit_holder_pos)
  167. {
  168. smax result = 0;
  169. umax int_bit_size = BIT_HOLDER_LENGTH - bit_holder_pos;
  170. // get the bias and subtract it right away
  171. result -= 1 * powerof_uint(2, int_bit_size - 1) - 1;
  172. // get the complete number as an unsigned integer and add it to result
  173. for (umax i = 0; i < int_bit_size; i++)
  174. result += BIT_HOLDER[BIT_HOLDER_LENGTH - i - 1] * powerof_uint(2, i);
  175. return result;
  176. }
  177. // bits_to_bminus2_sint() function
  178. // just like the unsigned integer calculation but using the -2 base
  179. smax bits_to_bminus2_sint(umax bit_holder_pos)
  180. {
  181. smax result = 0;
  182. umax int_bit_size = BIT_HOLDER_LENGTH - bit_holder_pos;
  183. // calculate the number as an unsigned integer but use base -2 instead of +2
  184. for (umax i = 0; i < int_bit_size; i++)
  185. result += BIT_HOLDER[BIT_HOLDER_LENGTH - i - 1] * powerof_sint(-2, i);
  186. return result;
  187. }
  188. /**********************************************************************
  189. * functions to calculate different type of integers from bits in memory
  190. ***********************************************************************/
  191. // UNSIGNED
  192. // calc_mem_std_uint() function
  193. umax calc_mem_std_uint(umax byte_cnt, umax lshifts, umax bit_cnt, umax lpad_cnt, void * src, ENDIAN_T endian)
  194. {
  195. return bits_to_std_uint(get_byte_bits(byte_cnt, lshifts, bit_cnt, lpad_cnt, src, endian));
  196. }
  197. // SIGNED
  198. // calc_mem_sign_mag_sint() function
  199. smax calc_mem_sign_mag_sint(umax byte_cnt, umax lshifts, umax bit_cnt, umax lpad_cnt, void * src, ENDIAN_T endian)
  200. {
  201. return bits_to_sign_mag_sint(get_byte_bits(byte_cnt, lshifts, bit_cnt, lpad_cnt, src, endian));
  202. }
  203. // calc_mem_1_compl_sint() function
  204. smax calc_mem_1_compl_sint(umax byte_cnt, umax lshifts, umax bit_cnt, umax lpad_cnt, void * src, ENDIAN_T endian)
  205. {
  206. return bits_to_1_compl_sint(get_byte_bits(byte_cnt, lshifts, bit_cnt, lpad_cnt, src, endian));
  207. }
  208. // calc_mem_2_compl_sint() function
  209. smax calc_mem_2_compl_sint(umax byte_cnt, umax lshifts, umax bit_cnt, umax lpad_cnt, void * src, ENDIAN_T endian)
  210. {
  211. return bits_to_2_compl_sint(get_byte_bits(byte_cnt, lshifts, bit_cnt, lpad_cnt, src, endian));
  212. }
  213. // calc_mem_off_bin_sint() function
  214. smax calc_mem_off_bin_sint(umax byte_cnt, umax lshifts, umax bit_cnt, umax lpad_cnt, void * src, ENDIAN_T endian)
  215. {
  216. return bits_to_off_bin_sint(get_byte_bits(byte_cnt, lshifts, bit_cnt, lpad_cnt, src, endian));
  217. }
  218. // calc_mem_bminus2_sint() function
  219. smax calc_mem_bminus2_sint(umax byte_cnt, umax lshifts, umax bit_cnt, umax lpad_cnt, void * src, ENDIAN_T endian)
  220. {
  221. return bits_to_bminus2_sint(get_byte_bits(byte_cnt, lshifts, bit_cnt, lpad_cnt, src, endian));
  222. }
  223. /********************************************
  224. * functions to get usual integers from memory
  225. * (not byte aligned, it is assumed the system
  226. * uses these types of integers)
  227. * - standard unsigned integer
  228. * - 2-complement signed integer
  229. *******************************/
  230. // get_uint() function
  231. // function to get a standard unsigned integer from memory without a manual calculation
  232. // method (assumes the system uses the std unsigned integer representation)
  233. // be careful with bit sizes that overflow umax!
  234. umax get_uint(umax byte_cnt, umax lshifts, umax bit_cnt, umax lpad_cnt, void * src, ENDIAN_T endian)
  235. {
  236. // variable to return
  237. umax result = 0;
  238. // get the bits from src
  239. get_byte_bits(byte_cnt, lshifts, bit_cnt, lpad_cnt, src, endian);
  240. // copy the bits into result
  241. cp_mem_bytes(BYTE_HOLDER + BYTE_HOLDER_LENGTH - sizeof(umax), sizeof(umax), &result);
  242. // modify byte order depending on SYS_ENDIAN
  243. if (SYS_ENDIAN == LITTLE)
  244. reverse_array(&result, sizeof(umax), sizeof(byte));
  245. // ^ as the bytes are already in big endian there is no need to
  246. // manage them after the copy process if the system is in big endian
  247. return result;
  248. }
  249. // get_sint() function
  250. // same as the above function but for signed integers
  251. // (2-complement ints are assumed to be used by the system)
  252. smax get_sint(umax byte_cnt, umax lshifts, umax bit_cnt, umax lpad_cnt, void * src, ENDIAN_T endian)
  253. {
  254. // variable to return and temp var
  255. smax result = 0, temp = 0;
  256. // get the bits from src
  257. result = get_uint(byte_cnt, lshifts, bit_cnt, lpad_cnt, src, endian);
  258. // get the left binary digits of the number container to be 1 and
  259. // make the binary digits ocupied by the actual integer to 0
  260. // then, add that binary digit result to the integer (to result)
  261. temp = (~ result) >> bit_cnt;
  262. temp = (temp << bit_cnt) + result;
  263. // check which one of the variables (result or temp) is outside the
  264. // signed integer range and return the one thats in (compare magnitude)
  265. result = (~ temp) > result ? result : temp;
  266. // bruh moment
  267. return result;
  268. }
  269. /****************************************
  270. * functions to get byte aligned and
  271. * specific sized usual integers in memory
  272. * I will call them "standard" (common)
  273. * integers (8, 16 and 32 bits long ints)
  274. *****************************************/
  275. // std_int_check() function
  276. // function to be used in the below functions
  277. bool std_int_check(umax bit_cnt);
  278. bool std_int_check(umax bit_cnt)
  279. {
  280. // return 0 if the bit size is not 8, 16 or 32
  281. if ((bit_cnt % 8) != 0 || bit_cnt > 32)
  282. return 0;
  283. return 1;
  284. }
  285. // get_std_uint() function
  286. // special case of the get_uint() function. bit_size is
  287. // limited to 8, 16 and 32 and the integer bits are byte aligned
  288. umax get_std_uint(umax bit_cnt, void * src, ENDIAN_T endian)
  289. {
  290. // get the unsigned integer if the bit size is valid
  291. if (std_int_check(bit_cnt))
  292. return get_uint(0, 0, bit_cnt, 0, src, endian);
  293. return 0;
  294. }
  295. // get_std_sint() function
  296. // same as get_std_uint() but for signed integers
  297. smax get_std_sint(umax bit_cnt, void * src, ENDIAN_T endian)
  298. {
  299. // get the signed integer if the bit size is valid
  300. if (std_int_check(bit_cnt))
  301. return get_sint(0, 0, bit_cnt, 0, src, endian);
  302. return 0;
  303. }
  304. // functions to print std integers
  305. // print_uint8() function
  306. umax print_uint8(void * ptr, umax size)
  307. {
  308. return print_byte_num(ptr, size);
  309. }
  310. // print_uint16be() function
  311. umax print_uint16be(void * ptr, umax size)
  312. {
  313. if (size < 2)
  314. return 0;
  315. printf("%llu", get_std_uint(16, ptr, BIG));
  316. return size;
  317. }
  318. // print_uint16le() function
  319. umax print_uint16le(void * ptr, umax size)
  320. {
  321. if (size < 2)
  322. return 0;
  323. printf("%llu", get_std_uint(16, ptr, LITTLE));
  324. return size;
  325. }
  326. // print_uint32be() function
  327. umax print_uint32be(void * ptr, umax size)
  328. {
  329. if (size < 4)
  330. return 0;
  331. printf("%llu", get_std_uint(32, ptr, BIG));
  332. return size;
  333. }
  334. // print_uint32le() function
  335. umax print_uint32le(void * ptr, umax size)
  336. {
  337. if (size < 4)
  338. return 0;
  339. printf("%llu", get_std_uint(32, ptr, LITTLE));
  340. return size;
  341. }
  342. // print_sint8() function
  343. umax print_sint8(void * ptr, umax size)
  344. {
  345. return print_char_num(ptr, size);
  346. }
  347. // print_sint16be() function
  348. umax print_sint16be(void * ptr, umax size)
  349. {
  350. if (size < 2)
  351. return 0;
  352. printf("%llu", get_std_sint(16, ptr, BIG));
  353. return size;
  354. }
  355. // print_sint16le() function
  356. umax print_sint16le(void * ptr, umax size)
  357. {
  358. if (size < 2)
  359. return 0;
  360. printf("%llu", get_std_sint(16, ptr, LITTLE));
  361. return size;
  362. }
  363. // print_sint32be() function
  364. umax print_sint32be(void * ptr, umax size)
  365. {
  366. if (size < 4)
  367. return 0;
  368. printf("%llu", get_std_sint(32, ptr, BIG));
  369. return size;
  370. }
  371. // print_sint32le() function
  372. umax print_sint32le(void * ptr, umax size)
  373. {
  374. if (size < 4)
  375. return 0;
  376. printf("%llu", get_std_sint(32, ptr, LITTLE));
  377. return size;
  378. }
  379. // Comparison functions
  380. // umax_equal() function
  381. // function to check if 2 umax integers are the same
  382. bool umax_equal(void * umax1, void * umax2)
  383. {
  384. return ((umax *) umax1)[0] == ((umax *) umax2)[0];
  385. }