aboutsummaryrefslogtreecommitdiff
path: root/src/stdlib
diff options
context:
space:
mode:
Diffstat (limited to 'src/stdlib')
-rw-r--r--src/stdlib/bytes.c8
-rw-r--r--src/stdlib/bytes.h1
-rw-r--r--src/stdlib/integers.c20
-rw-r--r--src/stdlib/integers.h2
4 files changed, 31 insertions, 0 deletions
diff --git a/src/stdlib/bytes.c b/src/stdlib/bytes.c
index b5c10aa2..48c8b93b 100644
--- a/src/stdlib/bytes.c
+++ b/src/stdlib/bytes.c
@@ -49,6 +49,14 @@ public Text_t Byte$hex(Byte_t byte, bool uppercase, bool prefix) {
return text;
}
+public bool Byte$get_bit(Byte_t x, Int_t bit_index) {
+ if (Int$compare_value(bit_index, I(1)) < 0)
+ fail("Invalid bit index (expected 1 or higher): ", bit_index);
+ if (Int$compare_value(bit_index, I(8)) > 0)
+ fail("Bit index is too large! There are only 8 bits in a byte, but index is: ", bit_index);
+ return ((x & (Byte_t)(1L << (Int64$from_int(bit_index, true)-1L))) != 0);
+}
+
#ifdef __TINYC__
#define __builtin_add_overflow(x, y, result) ({ *(result) = (x) + (y); false; })
#endif
diff --git a/src/stdlib/bytes.h b/src/stdlib/bytes.h
index 5c64687d..e733c274 100644
--- a/src/stdlib/bytes.h
+++ b/src/stdlib/bytes.h
@@ -30,5 +30,6 @@ extern const Byte_t Byte$max;
extern const TypeInfo_t Byte$info;
Text_t Byte$hex(Byte_t byte, bool uppercase, bool prefix);
+bool Byte$get_bit(Byte_t x, Int_t bit_index);
// vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1,\:0
diff --git a/src/stdlib/integers.c b/src/stdlib/integers.c
index 7c623663..018798ec 100644
--- a/src/stdlib/integers.c
+++ b/src/stdlib/integers.c
@@ -359,6 +359,19 @@ public OptionalInt_t Int$sqrt(Int_t i)
return Int$from_mpz(result);
}
+public bool Int$get_bit(Int_t x, Int_t bit_index)
+{
+ mpz_t i;
+ mpz_init_set_int(i, x);
+ if (Int$compare_value(bit_index, I(1)) < 0)
+ fail("Invalid bit index (expected 1 or higher): ", bit_index);
+ if (Int$compare_value(bit_index, Int$from_int64(INT64_MAX)) > 0)
+ fail("Bit index is too large! ", bit_index);
+
+ int is_bit_set = mpz_tstbit(i, (mp_bitcnt_t)(Int64$from_int(bit_index, true)-1));
+ return (bool)is_bit_set;
+}
+
typedef struct {
OptionalInt_t current, last;
Int_t step;
@@ -620,6 +633,13 @@ public void Int32$deserialize(FILE *in, void *outval, List_t *pointers, const Ty
} \
return bit_list; \
} \
+ public bool KindOfInt ## $get_bit(c_type x, Int_t bit_index) { \
+ if (Int$compare_value(bit_index, I(1)) < 0) \
+ fail("Invalid bit index (expected 1 or higher): ", bit_index); \
+ if (Int$compare_value(bit_index, Int$from_int64(sizeof(c_type)*8)) > 0) \
+ fail("Bit index is too large! There are only ", sizeof(c_type)*8, " bits, but index is: ", bit_index); \
+ return ((x & (c_type)(1L << (Int64$from_int(bit_index, true)-1L))) != 0); \
+ } \
typedef struct { \
Optional##KindOfInt##_t current, last; \
KindOfInt##_t step; \
diff --git a/src/stdlib/integers.h b/src/stdlib/integers.h
index 4eaac916..beb26bd6 100644
--- a/src/stdlib/integers.h
+++ b/src/stdlib/integers.h
@@ -29,6 +29,7 @@
Text_t type_name ## $hex(c_type i, Int_t digits, bool uppercase, bool prefix); \
Text_t type_name ## $octal(c_type i, Int_t digits, bool prefix); \
List_t type_name ## $bits(c_type x); \
+ bool type_name ## $get_bit(c_type x, Int_t bit_index); \
Closure_t type_name ## $to(c_type first, c_type last, Optional ## type_name ## _t step); \
Closure_t type_name ## $onward(c_type first, c_type step); \
PUREFUNC Optional ## type_name ## _t type_name ## $parse(Text_t text); \
@@ -105,6 +106,7 @@ Int_t Int$abs(Int_t x);
Int_t Int$power(Int_t base, Int_t exponent);
Int_t Int$gcd(Int_t x, Int_t y);
OptionalInt_t Int$sqrt(Int_t i);
+bool Int$get_bit(Int_t x, Int_t bit_index);
#define BIGGEST_SMALL_INT 0x3fffffff
#define SMALLEST_SMALL_INT -0x40000000