hare

[hare] The Hare programming language
git clone https://git.torresjrjr.com/hare.git
Log | Files | Refs | README | LICENSE

checked.ha (10381B)


      1 // SPDX-License-Identifier: MPL-2.0
      2 // (c) Hare authors <https://harelang.org>
      3 
      4 use math;
      5 
      6 // Adds 'a' and 'b', returning the result and whether overflow occurred.
      7 export fn addi8(a: i8, b: i8) (i8, bool) = {
      8 	const res = a + b;
      9 	const overflow = a < 0 == b < 0 && a < 0 != res < 0;
     10 	return (res, overflow);
     11 };
     12 
     13 @test fn addi8() void = {
     14 	const (res, overflow) = addi8(100, 20);
     15 	assert(res == 120);
     16 	assert(!overflow);
     17 	const (res, overflow) = addi8(100, 50);
     18 	assert(res == -106);
     19 	assert(overflow);
     20 };
     21 
     22 // Adds 'a' and 'b', returning the result and whether overflow occurred.
     23 export fn addi16(a: i16, b: i16) (i16, bool) = {
     24 	const res = a + b;
     25 	const overflow = a < 0 == b < 0 && a < 0 != res < 0;
     26 	return (res, overflow);
     27 };
     28 
     29 @test fn addi16() void = {
     30 	const (res, overflow) = addi16(32700, 60);
     31 	assert(res == 32760);
     32 	assert(!overflow);
     33 	const (res, overflow) = addi16(32700, 100);
     34 	assert(res == -32736);
     35 	assert(overflow);
     36 };
     37 
     38 // Adds 'a' and 'b', returning the result and whether overflow occurred.
     39 export fn addi32(a: i32, b: i32) (i32, bool) = {
     40 	const res = a + b;
     41 	const overflow = a < 0 == b < 0 && a < 0 != res < 0;
     42 	return (res, overflow);
     43 };
     44 
     45 @test fn addi32() void = {
     46 	const (res, overflow) = addi32(2147483600, 40);
     47 	assert(res == 2147483640);
     48 	assert(!overflow);
     49 	const (res, overflow) = addi32(2147483600, 100);
     50 	assert(res == -2147483596);
     51 	assert(overflow);
     52 };
     53 
     54 // Adds 'a' and 'b', returning the result and whether overflow occurred.
     55 export fn addi64(a: i64, b: i64) (i64, bool) = {
     56 	const res = a + b;
     57 	const overflow = a < 0 == b < 0 && a < 0 != res < 0;
     58 	return (res, overflow);
     59 };
     60 
     61 @test fn addi64() void = {
     62 	const (res, overflow) = addi64(9223372036854775800, 5);
     63 	assert(res == 9223372036854775805);
     64 	assert(!overflow);
     65 	const (res, overflow) = addi64(9223372036854775800, 10);
     66 	assert(res == -9223372036854775806);
     67 	assert(overflow);
     68 };
     69 
     70 // Adds 'a' and 'b', returning the result and whether overflow occurred.
     71 export fn addu8(a: u8, b: u8) (u8, bool) = {
     72 	const res = a + b;
     73 	const overflow = res < a;
     74 	return (res, overflow);
     75 };
     76 
     77 @test fn addu8() void = {
     78 	const (res, overflow) = addu8(200, 50);
     79 	assert(res == 250);
     80 	assert(!overflow);
     81 	const (res, overflow) = addu8(200, 100);
     82 	assert(res == 44);
     83 	assert(overflow);
     84 };
     85 
     86 // Adds 'a' and 'b', returning the result and whether overflow occurred.
     87 export fn addu16(a: u16, b: u16) (u16, bool) = {
     88 	const res = a + b;
     89 	const overflow = res < a;
     90 	return (res, overflow);
     91 };
     92 
     93 @test fn addu16() void = {
     94 	const (res, overflow) = addu16(65500, 30);
     95 	assert(res == 65530);
     96 	assert(!overflow);
     97 	const (res, overflow) = addu16(65500, 50);
     98 	assert(res == 14);
     99 	assert(overflow);
    100 };
    101 
    102 // Adds 'a' and 'b', returning the result and whether overflow occurred.
    103 export fn addu32(a: u32, b: u32) (u32, bool) = {
    104 	const res = a + b;
    105 	const overflow = res < a;
    106 	return (res, overflow);
    107 };
    108 
    109 @test fn addu32() void = {
    110 	const (res, overflow) = addu32(4294967200, 90);
    111 	assert(res == 4294967290);
    112 	assert(!overflow);
    113 	const (res, overflow) = addu32(4294967200, 100);
    114 	assert(res == 4);
    115 	assert(overflow);
    116 };
    117 
    118 // Adds 'a' and 'b', returning the result and whether overflow occurred.
    119 export fn addu64(a: u64, b: u64) (u64, bool) = {
    120 	const res = a + b;
    121 	const overflow = res < a;
    122 	return (res, overflow);
    123 };
    124 
    125 @test fn addu64() void = {
    126 	const (res, overflow) = addu64(18446744073709551600, 10);
    127 	assert(res == 18446744073709551610);
    128 	assert(!overflow);
    129 	const (res, overflow) = addu64(18446744073709551610, 50);
    130 	assert(res == 44);
    131 	assert(overflow);
    132 };
    133 
    134 // Subtracts 'b' from 'a', returning the result and whether overflow occurred.
    135 export fn subi8(a: i8, b: i8) (i8, bool) = addi8(a, -b);
    136 
    137 @test fn subi8() void = {
    138 	const (res, overflow) = subi8(-100, 20);
    139 	assert(res == -120);
    140 	assert(!overflow);
    141 	const (res, overflow) = subi8(-100, 50);
    142 	assert(res == 106);
    143 	assert(overflow);
    144 };
    145 
    146 // Subtracts 'b' from 'a', returning the result and whether overflow occurred.
    147 export fn subi16(a: i16, b: i16) (i16, bool) = addi16(a, -b);
    148 
    149 @test fn subi16() void = {
    150 	const (res, overflow) = subi16(-32700, 60);
    151 	assert(res == -32760);
    152 	assert(!overflow);
    153 	const (res, overflow) = subi16(-32700, 100);
    154 	assert(res == 32736);
    155 	assert(overflow);
    156 };
    157 
    158 // Subtracts 'b' from 'a', returning the result and whether overflow occurred.
    159 export fn subi32(a: i32, b: i32) (i32, bool) = addi32(a, -b);
    160 
    161 @test fn subi32() void = {
    162 	const (res, overflow) = subi32(-2147483600, 40);
    163 	assert(res == -2147483640);
    164 	assert(!overflow);
    165 	const (res, overflow) = subi32(-2147483600, 100);
    166 	assert(res == 2147483596);
    167 	assert(overflow);
    168 };
    169 
    170 // Subtracts 'b' from 'a', returning the result and whether overflow occurred.
    171 export fn subi64(a: i64, b: i64) (i64, bool) = addi64(a, -b);
    172 
    173 @test fn subi64() void = {
    174 	const (res, overflow) = subi64(-9223372036854775800, 5);
    175 	assert(res == -9223372036854775805);
    176 	assert(!overflow);
    177 	const (res, overflow) = subi64(-9223372036854775800, 10);
    178 	assert(res == 9223372036854775806);
    179 	assert(overflow);
    180 };
    181 
    182 // Subtracts 'b' from 'a', returning the result and whether overflow occurred.
    183 export fn subu8(a: u8, b: u8) (u8, bool) = {
    184 	const res = a - b;
    185 	const overflow = res > a;
    186 	return (res, overflow);
    187 };
    188 
    189 @test fn subu8() void = {
    190 	const (res, overflow) = subu8(250, 50);
    191 	assert(res == 200);
    192 	assert(!overflow);
    193 	const (res, overflow) = subu8(44, 100);
    194 	assert(res == 200);
    195 	assert(overflow);
    196 };
    197 
    198 // Subtracts 'b' from 'a', returning the result and whether overflow occurred.
    199 export fn subu16(a: u16, b: u16) (u16, bool) = {
    200 	const res = a - b;
    201 	const overflow = res > a;
    202 	return (res, overflow);
    203 };
    204 
    205 @test fn subu16() void = {
    206 	const (res, overflow) = subu16(65530, 30);
    207 	assert(res == 65500);
    208 	assert(!overflow);
    209 	const (res, overflow) = subu16(14, 50);
    210 	assert(res == 65500);
    211 	assert(overflow);
    212 };
    213 
    214 // Subtracts 'b' from 'a', returning the result and whether overflow occurred.
    215 export fn subu32(a: u32, b: u32) (u32, bool) = {
    216 	const res = a - b;
    217 	const overflow = res > a;
    218 	return (res, overflow);
    219 };
    220 
    221 @test fn subu32() void = {
    222 	const (res, overflow) = subu32(4294967290, 90);
    223 	assert(res == 4294967200);
    224 	assert(!overflow);
    225 	const (res, overflow) = subu32(4, 100);
    226 	assert(res == 4294967200);
    227 	assert(overflow);
    228 };
    229 
    230 // Subtracts 'b' from 'a', returning the result and whether overflow occurred.
    231 export fn subu64(a: u64, b: u64) (u64, bool) = {
    232 	const res = a - b;
    233 	const overflow = res > a;
    234 	return (res, overflow);
    235 };
    236 
    237 @test fn subu64() void = {
    238 	const (res, overflow) = subu64(18446744073709551610, 10);
    239 	assert(res == 18446744073709551600);
    240 	assert(!overflow);
    241 	const (res, overflow) = subu64(44, 50);
    242 	assert(res == 18446744073709551610);
    243 	assert(overflow);
    244 };
    245 
    246 // Multiplies 'a' and 'b' returning the result and whether overflow occurred.
    247 export fn muli8(a: i8, b: i8) (i8, bool) = {
    248 	const fullres = a: i16 * b: i16;
    249 	const res = fullres: i8;
    250 	const overflow = res != fullres;
    251 	return (res, overflow);
    252 };
    253 
    254 @test fn muli8() void = {
    255 	const (res, overflow) = muli8(11, 11);
    256 	assert(res == 121);
    257 	assert(!overflow);
    258 	const (res, overflow) = muli8(12, 12);
    259 	assert(res == -112);
    260 	assert(overflow);
    261 };
    262 
    263 // Multiplies 'a' and 'b' returning the result and whether overflow occurred.
    264 export fn muli16(a: i16, b: i16) (i16, bool) = {
    265 	const fullres = a: i32 * b: i32;
    266 	const res = fullres: i16;
    267 	const overflow = res != fullres;
    268 	return (res, overflow);
    269 };
    270 
    271 @test fn muli16() void = {
    272 	const (res, overflow) = muli16(181, 181);
    273 	assert(res == 32761);
    274 	assert(!overflow);
    275 	const (res, overflow) = muli16(182, 182);
    276 	assert(res == -32412);
    277 	assert(overflow);
    278 };
    279 
    280 // Multiplies 'a' and 'b' returning the result and whether overflow occurred.
    281 export fn muli32(a: i32, b: i32) (i32, bool) = {
    282 	const fullres = a: i64 * b: i64;
    283 	const res = fullres: i32;
    284 	const overflow = res != fullres;
    285 	return (res, overflow);
    286 };
    287 
    288 @test fn muli32() void = {
    289 	const (res, overflow) = muli32(46340, 46340);
    290 	assert(res == 2147395600);
    291 	assert(!overflow);
    292 	const (res, overflow) = muli32(46341, 46341);
    293 	assert(res == -2147479015);
    294 	assert(overflow);
    295 };
    296 
    297 // Multiplies 'a' and 'b' returning the result and whether overflow occurred.
    298 export fn muli64(a: i64, b: i64) (i64, bool) = {
    299 	const (hi, lo) = math::mulu64(math::absi64(a), math::absi64(b));
    300 	const res = a * b;
    301 	const overflow = hi != 0 || lo & (1 << 63) != 0;
    302 	return (res, overflow);
    303 };
    304 
    305 @test fn muli64() void = {
    306 	const (res, overflow) = muli64(3037000499, 3037000499);
    307 	assert(res == 9223372030926249001);
    308 	assert(!overflow);
    309 	const (res, overflow) = muli64(3037000500, 3037000500);
    310 	assert(res == -9223372036709301616);
    311 	assert(overflow);
    312 };
    313 
    314 // Multiplies 'a' and 'b' returning the result and whether overflow occurred.
    315 export fn mulu8(a: u8, b: u8) (u8, bool) = {
    316 	const fullres = a: u16 * b: u16;
    317 	const res = fullres: u8;
    318 	const overflow = res != fullres;
    319 	return (res, overflow);
    320 };
    321 
    322 @test fn mulu8() void = {
    323 	const (res, overflow) = mulu8(15, 15);
    324 	assert(res == 225);
    325 	assert(!overflow);
    326 	const (res, overflow) = mulu8(16, 16);
    327 	assert(res == 0);
    328 	assert(overflow);
    329 };
    330 
    331 // Multiplies 'a' and 'b' returning the result and whether overflow occurred.
    332 export fn mulu16(a: u16, b: u16) (u16, bool) = {
    333 	const fullres = a: u32 * b: u32;
    334 	const res = fullres: u16;
    335 	const overflow = res != fullres;
    336 	return (res, overflow);
    337 };
    338 
    339 @test fn mulu16() void = {
    340 	const (res, overflow) = mulu16(255, 255);
    341 	assert(res == 65025);
    342 	assert(!overflow);
    343 	const (res, overflow) = mulu16(256, 256);
    344 	assert(res == 0);
    345 	assert(overflow);
    346 };
    347 
    348 // Multiplies 'a' and 'b' returning the result and whether overflow occurred.
    349 export fn mulu32(a: u32, b: u32) (u32, bool) = {
    350 	const fullres = a: u64 * b: u64;
    351 	const res = fullres: u32;
    352 	const overflow = res != fullres;
    353 	return (res, overflow);
    354 };
    355 
    356 @test fn mulu32() void = {
    357 	const (res, overflow) = mulu32(65535, 65535);
    358 	assert(res == 4294836225);
    359 	assert(!overflow);
    360 	const (res, overflow) = mulu32(65536, 65536);
    361 	assert(res == 0);
    362 	assert(overflow);
    363 };
    364 
    365 // Multiplies 'a' and 'b' returning the result and whether overflow occurred.
    366 export fn mulu64(a: u64, b: u64) (u64, bool) = {
    367 	const (hi, lo) = math::mulu64(a, b);
    368 	const res = lo;
    369 	const overflow = hi != 0;
    370 	return (res, overflow);
    371 };
    372 
    373 @test fn mulu64() void = {
    374 	const (res, overflow) = mulu64(4294967295, 4294967295);
    375 	assert(res == 18446744065119617025);
    376 	assert(!overflow);
    377 	const (res, overflow) = mulu64(4294967296, 4294967296);
    378 	assert(res == 0);
    379 	assert(overflow);
    380 };