hare

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

checked.ha (13297B)


      1 // SPDX-License-Identifier: MPL-2.0
      2 // (c) Hare authors <https://harelang.org>
      3 
      4 use math;
      5 use types;
      6 
      7 // Adds 'a' and 'b', returning the result and whether overflow occurred.
      8 export fn addi8(a: i8, b: i8) (i8, bool) = {
      9 	const res = a + b;
     10 	const overflow = a < 0 == b < 0 && a < 0 != res < 0;
     11 	return (res, overflow);
     12 };
     13 
     14 @test fn addi8() void = {
     15 	const (res, overflow) = addi8(100, 20);
     16 	assert(res == 120);
     17 	assert(!overflow);
     18 	const (res, overflow) = addi8(100, 50);
     19 	assert(res == -106);
     20 	assert(overflow);
     21 };
     22 
     23 // Adds 'a' and 'b', returning the result and whether overflow occurred.
     24 export fn addi16(a: i16, b: i16) (i16, bool) = {
     25 	const res = a + b;
     26 	const overflow = a < 0 == b < 0 && a < 0 != res < 0;
     27 	return (res, overflow);
     28 };
     29 
     30 @test fn addi16() void = {
     31 	const (res, overflow) = addi16(32700, 60);
     32 	assert(res == 32760);
     33 	assert(!overflow);
     34 	const (res, overflow) = addi16(32700, 100);
     35 	assert(res == -32736);
     36 	assert(overflow);
     37 };
     38 
     39 // Adds 'a' and 'b', returning the result and whether overflow occurred.
     40 export fn addi32(a: i32, b: i32) (i32, bool) = {
     41 	const res = a + b;
     42 	const overflow = a < 0 == b < 0 && a < 0 != res < 0;
     43 	return (res, overflow);
     44 };
     45 
     46 @test fn addi32() void = {
     47 	const (res, overflow) = addi32(2147483600, 40);
     48 	assert(res == 2147483640);
     49 	assert(!overflow);
     50 	const (res, overflow) = addi32(2147483600, 100);
     51 	assert(res == -2147483596);
     52 	assert(overflow);
     53 };
     54 
     55 // Adds 'a' and 'b', returning the result and whether overflow occurred.
     56 export fn addi64(a: i64, b: i64) (i64, bool) = {
     57 	const res = a + b;
     58 	const overflow = a < 0 == b < 0 && a < 0 != res < 0;
     59 	return (res, overflow);
     60 };
     61 
     62 @test fn addi64() void = {
     63 	const (res, overflow) = addi64(9223372036854775800, 5);
     64 	assert(res == 9223372036854775805);
     65 	assert(!overflow);
     66 	const (res, overflow) = addi64(9223372036854775800, 10);
     67 	assert(res == -9223372036854775806);
     68 	assert(overflow);
     69 };
     70 
     71 // Adds 'a' and 'b', returning the result and whether overflow occurred.
     72 export fn addi(a: int, b: int) (int, bool) = {
     73 	const res = a + b;
     74 	const overflow = a < 0 == b < 0 && a < 0 != res < 0;
     75 	return (res, overflow);
     76 };
     77 
     78 // Adds 'a' and 'b', returning the result and whether overflow occurred.
     79 export fn addu8(a: u8, b: u8) (u8, bool) = {
     80 	const res = a + b;
     81 	const overflow = res < a;
     82 	return (res, overflow);
     83 };
     84 
     85 @test fn addu8() void = {
     86 	const (res, overflow) = addu8(200, 50);
     87 	assert(res == 250);
     88 	assert(!overflow);
     89 	const (res, overflow) = addu8(200, 100);
     90 	assert(res == 44);
     91 	assert(overflow);
     92 };
     93 
     94 // Adds 'a' and 'b', returning the result and whether overflow occurred.
     95 export fn addu16(a: u16, b: u16) (u16, bool) = {
     96 	const res = a + b;
     97 	const overflow = res < a;
     98 	return (res, overflow);
     99 };
    100 
    101 @test fn addu16() void = {
    102 	const (res, overflow) = addu16(65500, 30);
    103 	assert(res == 65530);
    104 	assert(!overflow);
    105 	const (res, overflow) = addu16(65500, 50);
    106 	assert(res == 14);
    107 	assert(overflow);
    108 };
    109 
    110 // Adds 'a' and 'b', returning the result and whether overflow occurred.
    111 export fn addu32(a: u32, b: u32) (u32, bool) = {
    112 	const res = a + b;
    113 	const overflow = res < a;
    114 	return (res, overflow);
    115 };
    116 
    117 @test fn addu32() void = {
    118 	const (res, overflow) = addu32(4294967200, 90);
    119 	assert(res == 4294967290);
    120 	assert(!overflow);
    121 	const (res, overflow) = addu32(4294967200, 100);
    122 	assert(res == 4);
    123 	assert(overflow);
    124 };
    125 
    126 // Adds 'a' and 'b', returning the result and whether overflow occurred.
    127 export fn addu64(a: u64, b: u64) (u64, bool) = {
    128 	const res = a + b;
    129 	const overflow = res < a;
    130 	return (res, overflow);
    131 };
    132 
    133 @test fn addu64() void = {
    134 	const (res, overflow) = addu64(18446744073709551600, 10);
    135 	assert(res == 18446744073709551610);
    136 	assert(!overflow);
    137 	const (res, overflow) = addu64(18446744073709551610, 50);
    138 	assert(res == 44);
    139 	assert(overflow);
    140 };
    141 
    142 // Adds 'a' and 'b', returning the result and whether overflow occurred.
    143 export fn addu(a: uint, b: uint) (uint, bool) = {
    144 	const res = a + b;
    145 	const overflow = res < a;
    146 	return (res, overflow);
    147 };
    148 
    149 // Adds 'a' and 'b', returning the result and whether overflow occurred.
    150 export fn addz(a: size, b: size) (size, bool) = {
    151 	const res = a + b;
    152 	const overflow = res < a;
    153 	return (res, overflow);
    154 };
    155 
    156 // Subtracts 'b' from 'a', returning the result and whether overflow occurred.
    157 export fn subi8(a: i8, b: i8) (i8, bool) = {
    158 	const res = a - b;
    159 	const overflow = a < 0 != b < 0 && a < 0 != res < 0;
    160 	return (res, overflow);
    161 };
    162 
    163 @test fn subi8() void = {
    164 	const (res, overflow) = subi8(-100, 20);
    165 	assert(res == -120);
    166 	assert(!overflow);
    167 	const (res, overflow) = subi8(-100, 50);
    168 	assert(res == 106);
    169 	assert(overflow);
    170 	const (res, overflow) = subi8(types::I8_MAX, types::I8_MIN);
    171 	assert(res == -1);
    172 	assert(overflow);
    173 };
    174 
    175 // Subtracts 'b' from 'a', returning the result and whether overflow occurred.
    176 export fn subi16(a: i16, b: i16) (i16, bool) = {
    177 	const res = a - b;
    178 	const overflow = a < 0 != b < 0 && a < 0 != res < 0;
    179 	return (res, overflow);
    180 };
    181 
    182 @test fn subi16() void = {
    183 	const (res, overflow) = subi16(-32700, 60);
    184 	assert(res == -32760);
    185 	assert(!overflow);
    186 	const (res, overflow) = subi16(-32700, 100);
    187 	assert(res == 32736);
    188 	assert(overflow);
    189 	const (res, overflow) = subi16(types::I16_MAX, types::I16_MIN);
    190 	assert(res == -1);
    191 	assert(overflow);
    192 };
    193 
    194 // Subtracts 'b' from 'a', returning the result and whether overflow occurred.
    195 export fn subi32(a: i32, b: i32) (i32, bool) = {
    196 	const res = a - b;
    197 	const overflow = a < 0 != b < 0 && a < 0 != res < 0;
    198 	return (res, overflow);
    199 };
    200 
    201 @test fn subi32() void = {
    202 	const (res, overflow) = subi32(-2147483600, 40);
    203 	assert(res == -2147483640);
    204 	assert(!overflow);
    205 	const (res, overflow) = subi32(-2147483600, 100);
    206 	assert(res == 2147483596);
    207 	assert(overflow);
    208 	const (res, overflow) = subi32(types::I32_MAX, types::I32_MIN);
    209 	assert(res == -1);
    210 	assert(overflow);
    211 };
    212 
    213 // Subtracts 'b' from 'a', returning the result and whether overflow occurred.
    214 export fn subi64(a: i64, b: i64) (i64, bool) = {
    215 	const res = a - b;
    216 	const overflow = a < 0 != b < 0 && a < 0 != res < 0;
    217 	return (res, overflow);
    218 };
    219 
    220 @test fn subi64() void = {
    221 	const (res, overflow) = subi64(-9223372036854775800, 5);
    222 	assert(res == -9223372036854775805);
    223 	assert(!overflow);
    224 	const (res, overflow) = subi64(-9223372036854775800, 10);
    225 	assert(res == 9223372036854775806);
    226 	assert(overflow);
    227 	const (res, overflow) = subi64(types::I64_MAX, types::I64_MIN);
    228 	assert(res == -1);
    229 	assert(overflow);
    230 };
    231 
    232 // Subtracts 'b' from 'a', returning the result and whether overflow occurred.
    233 export fn subi(a: int, b: int) (int, bool) = {
    234 	const res = a - b;
    235 	const overflow = a < 0 != b < 0 && a < 0 != res < 0;
    236 	return (res, overflow);
    237 };
    238 
    239 // Subtracts 'b' from 'a', returning the result and whether overflow occurred.
    240 export fn subu8(a: u8, b: u8) (u8, bool) = {
    241 	const res = a - b;
    242 	const overflow = res > a;
    243 	return (res, overflow);
    244 };
    245 
    246 @test fn subu8() void = {
    247 	const (res, overflow) = subu8(250, 50);
    248 	assert(res == 200);
    249 	assert(!overflow);
    250 	const (res, overflow) = subu8(44, 100);
    251 	assert(res == 200);
    252 	assert(overflow);
    253 };
    254 
    255 // Subtracts 'b' from 'a', returning the result and whether overflow occurred.
    256 export fn subu16(a: u16, b: u16) (u16, bool) = {
    257 	const res = a - b;
    258 	const overflow = res > a;
    259 	return (res, overflow);
    260 };
    261 
    262 @test fn subu16() void = {
    263 	const (res, overflow) = subu16(65530, 30);
    264 	assert(res == 65500);
    265 	assert(!overflow);
    266 	const (res, overflow) = subu16(14, 50);
    267 	assert(res == 65500);
    268 	assert(overflow);
    269 };
    270 
    271 // Subtracts 'b' from 'a', returning the result and whether overflow occurred.
    272 export fn subu32(a: u32, b: u32) (u32, bool) = {
    273 	const res = a - b;
    274 	const overflow = res > a;
    275 	return (res, overflow);
    276 };
    277 
    278 @test fn subu32() void = {
    279 	const (res, overflow) = subu32(4294967290, 90);
    280 	assert(res == 4294967200);
    281 	assert(!overflow);
    282 	const (res, overflow) = subu32(4, 100);
    283 	assert(res == 4294967200);
    284 	assert(overflow);
    285 };
    286 
    287 // Subtracts 'b' from 'a', returning the result and whether overflow occurred.
    288 export fn subu64(a: u64, b: u64) (u64, bool) = {
    289 	const res = a - b;
    290 	const overflow = res > a;
    291 	return (res, overflow);
    292 };
    293 
    294 @test fn subu64() void = {
    295 	const (res, overflow) = subu64(18446744073709551610, 10);
    296 	assert(res == 18446744073709551600);
    297 	assert(!overflow);
    298 	const (res, overflow) = subu64(44, 50);
    299 	assert(res == 18446744073709551610);
    300 	assert(overflow);
    301 };
    302 
    303 // Subtracts 'b' from 'a', returning the result and whether overflow occurred.
    304 export fn subu(a: uint, b: uint) (uint, bool) = {
    305 	const res = a - b;
    306 	const overflow = res > a;
    307 	return (res, overflow);
    308 };
    309 
    310 // Subtracts 'b' from 'a', returning the result and whether overflow occurred.
    311 export fn subz(a: size, b: size) (size, bool) = {
    312 	const res = a - b;
    313 	const overflow = res > a;
    314 	return (res, overflow);
    315 };
    316 
    317 // Multiplies 'a' and 'b' returning the result and whether overflow occurred.
    318 export fn muli8(a: i8, b: i8) (i8, bool) = {
    319 	const fullres = a: int * b: int;
    320 	const res = fullres: i8;
    321 	const overflow = res != fullres;
    322 	return (res, overflow);
    323 };
    324 
    325 @test fn muli8() void = {
    326 	const (res, overflow) = muli8(11, 11);
    327 	assert(res == 121);
    328 	assert(!overflow);
    329 	const (res, overflow) = muli8(12, 12);
    330 	assert(res == -112);
    331 	assert(overflow);
    332 };
    333 
    334 // Multiplies 'a' and 'b' returning the result and whether overflow occurred.
    335 export fn muli16(a: i16, b: i16) (i16, bool) = {
    336 	const fullres = a: int * b: int;
    337 	const res = fullres: i16;
    338 	const overflow = res != fullres;
    339 	return (res, overflow);
    340 };
    341 
    342 @test fn muli16() void = {
    343 	const (res, overflow) = muli16(181, 181);
    344 	assert(res == 32761);
    345 	assert(!overflow);
    346 	const (res, overflow) = muli16(182, 182);
    347 	assert(res == -32412);
    348 	assert(overflow);
    349 };
    350 
    351 // Multiplies 'a' and 'b' returning the result and whether overflow occurred.
    352 export fn muli32(a: i32, b: i32) (i32, bool) = {
    353 	const fullres = a: i64 * b: i64;
    354 	const res = fullres: i32;
    355 	const overflow = res != fullres;
    356 	return (res, overflow);
    357 };
    358 
    359 @test fn muli32() void = {
    360 	const (res, overflow) = muli32(46340, 46340);
    361 	assert(res == 2147395600);
    362 	assert(!overflow);
    363 	const (res, overflow) = muli32(46341, 46341);
    364 	assert(res == -2147479015);
    365 	assert(overflow);
    366 };
    367 
    368 // Multiplies 'a' and 'b' returning the result and whether overflow occurred.
    369 export fn muli64(a: i64, b: i64) (i64, bool) = {
    370 	const (hi, lo) = math::mulu64(math::absi64(a), math::absi64(b));
    371 	const res = a * b;
    372 	const overflow = hi != 0 || lo & (1 << 63) != 0;
    373 	return (res, overflow);
    374 };
    375 
    376 @test fn muli64() void = {
    377 	const (res, overflow) = muli64(3037000499, 3037000499);
    378 	assert(res == 9223372030926249001);
    379 	assert(!overflow);
    380 	const (res, overflow) = muli64(3037000500, 3037000500);
    381 	assert(res == -9223372036709301616);
    382 	assert(overflow);
    383 };
    384 
    385 // Multiplies 'a' and 'b' returning the result and whether overflow occurred.
    386 export fn muli(a: int, b: int) (int, bool) = {
    387 	if (size(int) == 4) {
    388 		const ret = muli32(a: i32, b: i32);
    389 		return (ret.0, ret.1);
    390 	} else {
    391 		const ret = muli64(a, b);
    392 		return (ret.0: int, ret.1);
    393 	};
    394 };
    395 
    396 // Multiplies 'a' and 'b' returning the result and whether overflow occurred.
    397 export fn mulu8(a: u8, b: u8) (u8, bool) = {
    398 	const fullres = a: uint * b: uint;
    399 	const res = fullres: u8;
    400 	const overflow = res != fullres;
    401 	return (res, overflow);
    402 };
    403 
    404 @test fn mulu8() void = {
    405 	const (res, overflow) = mulu8(15, 15);
    406 	assert(res == 225);
    407 	assert(!overflow);
    408 	const (res, overflow) = mulu8(16, 16);
    409 	assert(res == 0);
    410 	assert(overflow);
    411 };
    412 
    413 // Multiplies 'a' and 'b' returning the result and whether overflow occurred.
    414 export fn mulu16(a: u16, b: u16) (u16, bool) = {
    415 	const fullres = a: uint * b: uint;
    416 	const res = fullres: u16;
    417 	const overflow = res != fullres;
    418 	return (res, overflow);
    419 };
    420 
    421 @test fn mulu16() void = {
    422 	const (res, overflow) = mulu16(255, 255);
    423 	assert(res == 65025);
    424 	assert(!overflow);
    425 	const (res, overflow) = mulu16(256, 256);
    426 	assert(res == 0);
    427 	assert(overflow);
    428 };
    429 
    430 // Multiplies 'a' and 'b' returning the result and whether overflow occurred.
    431 export fn mulu32(a: u32, b: u32) (u32, bool) = {
    432 	const fullres = a: u64 * b: u64;
    433 	const res = fullres: u32;
    434 	const overflow = res != fullres;
    435 	return (res, overflow);
    436 };
    437 
    438 @test fn mulu32() void = {
    439 	const (res, overflow) = mulu32(65535, 65535);
    440 	assert(res == 4294836225);
    441 	assert(!overflow);
    442 	const (res, overflow) = mulu32(65536, 65536);
    443 	assert(res == 0);
    444 	assert(overflow);
    445 };
    446 
    447 // Multiplies 'a' and 'b' returning the result and whether overflow occurred.
    448 export fn mulu64(a: u64, b: u64) (u64, bool) = {
    449 	const (hi, lo) = math::mulu64(a, b);
    450 	const res = lo;
    451 	const overflow = hi != 0;
    452 	return (res, overflow);
    453 };
    454 
    455 @test fn mulu64() void = {
    456 	const (res, overflow) = mulu64(4294967295, 4294967295);
    457 	assert(res == 18446744065119617025);
    458 	assert(!overflow);
    459 	const (res, overflow) = mulu64(4294967296, 4294967296);
    460 	assert(res == 0);
    461 	assert(overflow);
    462 };
    463 
    464 // Multiplies 'a' and 'b' returning the result and whether overflow occurred.
    465 export fn mulu(a: uint, b: uint) (uint, bool) = {
    466 	if (size(uint) == 4) {
    467 		const ret = mulu32(a: u32, b: u32);
    468 		return (ret.0, ret.1);
    469 	} else {
    470 		const ret = mulu64(a, b);
    471 		return (ret.0: uint, ret.1);
    472 	};
    473 };
    474 
    475 // Multiplies 'a' and 'b' returning the result and whether overflow occurred.
    476 export fn mulz(a: size, b: size) (size, bool) = {
    477 	if (size(size) == 4) {
    478 		const ret = mulu32(a: u32, b: u32);
    479 		return (ret.0, ret.1);
    480 	} else {
    481 		const ret = mulu64(a, b);
    482 		return (ret.0: size, ret.1);
    483 	};
    484 };