TestWrappingOperations.cpp (25913B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this file, 5 * You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #include "mozilla/Assertions.h" 8 #include "mozilla/WrappingOperations.h" 9 10 #include <stdint.h> 11 12 using mozilla::WrappingAdd; 13 using mozilla::WrappingMultiply; 14 using mozilla::WrappingSubtract; 15 using mozilla::WrapToSigned; 16 17 // NOTE: In places below |-FOO_MAX - 1| is used instead of |-FOO_MIN| because 18 // in C++ numeric literals are full expressions -- the |-| in a negative 19 // number is technically separate. So with most compilers that limit 20 // |int| to the signed 32-bit range, something like |-2147483648| is 21 // operator-() applied to an *unsigned* expression. And MSVC, at least, 22 // warns when you do that. (The operation is well-defined, but it likely 23 // doesn't do what was intended.) So we do the usual workaround for this 24 // (see your local copy of <stdint.h> for a likely demo of this), writing 25 // it out by negating the max value and subtracting 1. 26 27 static_assert(WrapToSigned(uint8_t(17)) == 17, 28 "no wraparound should work, 8-bit"); 29 static_assert(WrapToSigned(uint8_t(128)) == -128, 30 "works for 8-bit numbers, wraparound low end"); 31 static_assert(WrapToSigned(uint8_t(128 + 7)) == -128 + 7, 32 "works for 8-bit numbers, wraparound mid"); 33 static_assert(WrapToSigned(uint8_t(128 + 127)) == -128 + 127, 34 "works for 8-bit numbers, wraparound high end"); 35 36 static_assert(WrapToSigned(uint16_t(12345)) == 12345, 37 "no wraparound should work, 16-bit"); 38 static_assert(WrapToSigned(uint16_t(32768)) == -32768, 39 "works for 16-bit numbers, wraparound low end"); 40 static_assert(WrapToSigned(uint16_t(32768 + 42)) == -32768 + 42, 41 "works for 16-bit numbers, wraparound mid"); 42 static_assert(WrapToSigned(uint16_t(32768 + 32767)) == -32768 + 32767, 43 "works for 16-bit numbers, wraparound high end"); 44 45 static_assert(WrapToSigned(uint32_t(8675309)) == 8675309, 46 "no wraparound should work, 32-bit"); 47 static_assert(WrapToSigned(uint32_t(2147483648)) == -2147483647 - 1, 48 "works for 32-bit numbers, wraparound low end"); 49 static_assert(WrapToSigned(uint32_t(2147483648 + 42)) == -2147483647 - 1 + 42, 50 "works for 32-bit numbers, wraparound mid"); 51 static_assert(WrapToSigned(uint32_t(2147483648 + 2147483647)) == 52 -2147483647 - 1 + 2147483647, 53 "works for 32-bit numbers, wraparound high end"); 54 55 static_assert(WrapToSigned(uint64_t(4152739164)) == 4152739164, 56 "no wraparound should work, 64-bit"); 57 static_assert(WrapToSigned(uint64_t(9223372036854775808ULL)) == 58 -9223372036854775807LL - 1, 59 "works for 64-bit numbers, wraparound low end"); 60 static_assert(WrapToSigned(uint64_t(9223372036854775808ULL + 8005552368LL)) == 61 -9223372036854775807LL - 1 + 8005552368LL, 62 "works for 64-bit numbers, wraparound mid"); 63 static_assert(WrapToSigned(uint64_t(9223372036854775808ULL + 64 9223372036854775807ULL)) == 65 -9223372036854775807LL - 1 + 9223372036854775807LL, 66 "works for 64-bit numbers, wraparound high end"); 67 68 template <typename T> 69 inline constexpr bool TestEqual(T aX, T aY) { 70 return aX == aY; 71 } 72 73 static void TestWrappingAdd8() { 74 MOZ_RELEASE_ASSERT( 75 TestEqual(WrappingAdd(uint8_t(0), uint8_t(128)), uint8_t(128)), 76 "zero plus anything is anything"); 77 MOZ_RELEASE_ASSERT( 78 TestEqual(WrappingAdd(uint8_t(17), uint8_t(42)), uint8_t(59)), 79 "17 + 42 == 59"); 80 MOZ_RELEASE_ASSERT( 81 TestEqual(WrappingAdd(uint8_t(255), uint8_t(1)), uint8_t(0)), 82 "all bits plus one overflows to zero"); 83 MOZ_RELEASE_ASSERT( 84 TestEqual(WrappingAdd(uint8_t(128), uint8_t(127)), uint8_t(255)), 85 "high bit plus all lower bits is all bits"); 86 MOZ_RELEASE_ASSERT( 87 TestEqual(WrappingAdd(uint8_t(128), uint8_t(193)), uint8_t(65)), 88 "128 + 193 is 256 + 65"); 89 90 MOZ_RELEASE_ASSERT( 91 TestEqual(WrappingAdd(int8_t(0), int8_t(-128)), int8_t(-128)), 92 "zero plus anything is anything"); 93 MOZ_RELEASE_ASSERT( 94 TestEqual(WrappingAdd(int8_t(123), int8_t(8)), int8_t(-125)), 95 "overflow to negative"); 96 MOZ_RELEASE_ASSERT( 97 TestEqual(WrappingAdd(int8_t(5), int8_t(-123)), int8_t(-118)), 98 "5 - 123 is -118"); 99 MOZ_RELEASE_ASSERT( 100 TestEqual(WrappingAdd(int8_t(-85), int8_t(-73)), int8_t(98)), 101 "underflow to positive"); 102 MOZ_RELEASE_ASSERT( 103 TestEqual(WrappingAdd(int8_t(-128), int8_t(127)), int8_t(-1)), 104 "high bit plus all lower bits is -1"); 105 } 106 107 static void TestWrappingAdd16() { 108 MOZ_RELEASE_ASSERT( 109 TestEqual(WrappingAdd(uint16_t(0), uint16_t(32768)), uint16_t(32768)), 110 "zero plus anything is anything"); 111 MOZ_RELEASE_ASSERT( 112 TestEqual(WrappingAdd(uint16_t(24389), uint16_t(2682)), uint16_t(27071)), 113 "24389 + 2682 == 27071"); 114 MOZ_RELEASE_ASSERT( 115 TestEqual(WrappingAdd(uint16_t(65535), uint16_t(1)), uint16_t(0)), 116 "all bits plus one overflows to zero"); 117 MOZ_RELEASE_ASSERT( 118 TestEqual(WrappingAdd(uint16_t(32768), uint16_t(32767)), uint16_t(65535)), 119 "high bit plus all lower bits is all bits"); 120 MOZ_RELEASE_ASSERT( 121 TestEqual(WrappingAdd(uint16_t(32768), uint16_t(47582)), uint16_t(14814)), 122 "32768 + 47582 is 65536 + 14814"); 123 124 MOZ_RELEASE_ASSERT( 125 TestEqual(WrappingAdd(int16_t(0), int16_t(-32768)), int16_t(-32768)), 126 "zero plus anything is anything"); 127 MOZ_RELEASE_ASSERT( 128 TestEqual(WrappingAdd(int16_t(32765), int16_t(8)), int16_t(-32763)), 129 "overflow to negative"); 130 MOZ_RELEASE_ASSERT( 131 TestEqual(WrappingAdd(int16_t(5), int16_t(-28933)), int16_t(-28928)), 132 "5 - 28933 is -28928"); 133 MOZ_RELEASE_ASSERT( 134 TestEqual(WrappingAdd(int16_t(-23892), int16_t(-12893)), int16_t(28751)), 135 "underflow to positive"); 136 MOZ_RELEASE_ASSERT( 137 TestEqual(WrappingAdd(int16_t(-32768), int16_t(32767)), int16_t(-1)), 138 "high bit plus all lower bits is -1"); 139 } 140 141 static void TestWrappingAdd32() { 142 MOZ_RELEASE_ASSERT(TestEqual(WrappingAdd(uint32_t(0), uint32_t(2147483648)), 143 uint32_t(2147483648)), 144 "zero plus anything is anything"); 145 MOZ_RELEASE_ASSERT( 146 TestEqual(WrappingAdd(uint32_t(1398742328), uint32_t(714192829)), 147 uint32_t(2112935157)), 148 "1398742328 + 714192829 == 2112935157"); 149 MOZ_RELEASE_ASSERT( 150 TestEqual(WrappingAdd(uint32_t(4294967295), uint32_t(1)), uint32_t(0)), 151 "all bits plus one overflows to zero"); 152 MOZ_RELEASE_ASSERT( 153 TestEqual(WrappingAdd(uint32_t(2147483648), uint32_t(2147483647)), 154 uint32_t(4294967295)), 155 "high bit plus all lower bits is all bits"); 156 MOZ_RELEASE_ASSERT( 157 TestEqual(WrappingAdd(uint32_t(2147483648), uint32_t(3146492712)), 158 uint32_t(999009064)), 159 "2147483648 + 3146492712 is 4294967296 + 999009064"); 160 161 MOZ_RELEASE_ASSERT( 162 TestEqual(WrappingAdd(int32_t(0), int32_t(-2147483647 - 1)), 163 int32_t(-2147483647 - 1)), 164 "zero plus anything is anything"); 165 MOZ_RELEASE_ASSERT(TestEqual(WrappingAdd(int32_t(2147483645), int32_t(8)), 166 int32_t(-2147483643)), 167 "overflow to negative"); 168 MOZ_RELEASE_ASSERT(TestEqual(WrappingAdd(int32_t(257), int32_t(-23947248)), 169 int32_t(-23946991)), 170 "257 - 23947248 is -23946991"); 171 MOZ_RELEASE_ASSERT( 172 TestEqual(WrappingAdd(int32_t(-2147483220), int32_t(-12893)), 173 int32_t(2147471183)), 174 "underflow to positive"); 175 MOZ_RELEASE_ASSERT( 176 TestEqual(WrappingAdd(int32_t(-32768), int32_t(32767)), int32_t(-1)), 177 "high bit plus all lower bits is -1"); 178 } 179 180 static void TestWrappingAdd64() { 181 MOZ_RELEASE_ASSERT( 182 TestEqual(WrappingAdd(uint64_t(0), uint64_t(9223372036854775808ULL)), 183 uint64_t(9223372036854775808ULL)), 184 "zero plus anything is anything"); 185 MOZ_RELEASE_ASSERT( 186 TestEqual(WrappingAdd(uint64_t(70368744177664), uint64_t(3740873592)), 187 uint64_t(70372485051256)), 188 "70368744177664 + 3740873592 == 70372485051256"); 189 MOZ_RELEASE_ASSERT( 190 TestEqual(WrappingAdd(uint64_t(18446744073709551615ULL), uint64_t(1)), 191 uint64_t(0)), 192 "all bits plus one overflows to zero"); 193 MOZ_RELEASE_ASSERT(TestEqual(WrappingAdd(uint64_t(9223372036854775808ULL), 194 uint64_t(9223372036854775807ULL)), 195 uint64_t(18446744073709551615ULL)), 196 "high bit plus all lower bits is all bits"); 197 MOZ_RELEASE_ASSERT(TestEqual(WrappingAdd(uint64_t(14552598638644786479ULL), 198 uint64_t(3894174382537247221ULL)), 199 uint64_t(28947472482084)), 200 "9223372036854775808 + 3146492712 is 18446744073709551616 " 201 "+ 28947472482084"); 202 203 MOZ_RELEASE_ASSERT( 204 TestEqual(WrappingAdd(int64_t(0), int64_t(-9223372036854775807LL - 1)), 205 int64_t(-9223372036854775807LL - 1)), 206 "zero plus anything is anything"); 207 MOZ_RELEASE_ASSERT( 208 TestEqual(WrappingAdd(int64_t(9223372036854775802LL), int64_t(8)), 209 int64_t(-9223372036854775806LL)), 210 "overflow to negative"); 211 MOZ_RELEASE_ASSERT( 212 TestEqual(WrappingAdd(int64_t(37482739294298742LL), 213 int64_t(-437843573929483498LL)), 214 int64_t(-400360834635184756LL)), 215 "37482739294298742 - 437843573929483498 is -400360834635184756"); 216 MOZ_RELEASE_ASSERT(TestEqual(WrappingAdd(int64_t(-9127837934058953374LL), 217 int64_t(-4173572032144775807LL)), 218 int64_t(5145334107505822435L)), 219 "underflow to positive"); 220 MOZ_RELEASE_ASSERT(TestEqual(WrappingAdd(int64_t(-9223372036854775807LL - 1), 221 int64_t(9223372036854775807LL)), 222 int64_t(-1)), 223 "high bit plus all lower bits is -1"); 224 } 225 226 static void TestWrappingAdd() { 227 TestWrappingAdd8(); 228 TestWrappingAdd16(); 229 TestWrappingAdd32(); 230 TestWrappingAdd64(); 231 } 232 233 static void TestWrappingSubtract8() { 234 MOZ_RELEASE_ASSERT( 235 TestEqual(WrappingSubtract(uint8_t(0), uint8_t(128)), uint8_t(128)), 236 "zero minus half is half"); 237 MOZ_RELEASE_ASSERT( 238 TestEqual(WrappingSubtract(uint8_t(17), uint8_t(42)), uint8_t(231)), 239 "17 - 42 == -25 added to 256 is 231"); 240 MOZ_RELEASE_ASSERT( 241 TestEqual(WrappingSubtract(uint8_t(0), uint8_t(1)), uint8_t(255)), 242 "zero underflows to all bits"); 243 MOZ_RELEASE_ASSERT( 244 TestEqual(WrappingSubtract(uint8_t(128), uint8_t(127)), uint8_t(1)), 245 "128 - 127 == 1"); 246 MOZ_RELEASE_ASSERT( 247 TestEqual(WrappingSubtract(uint8_t(128), uint8_t(193)), uint8_t(191)), 248 "128 - 193 is -65 so -65 + 256 == 191"); 249 250 MOZ_RELEASE_ASSERT( 251 TestEqual(WrappingSubtract(int8_t(0), int8_t(-128)), int8_t(-128)), 252 "zero minus high bit wraps to high bit"); 253 MOZ_RELEASE_ASSERT( 254 TestEqual(WrappingSubtract(int8_t(-126), int8_t(4)), int8_t(126)), 255 "underflow to positive"); 256 MOZ_RELEASE_ASSERT( 257 TestEqual(WrappingSubtract(int8_t(5), int8_t(-123)), int8_t(-128)), 258 "overflow to negative"); 259 MOZ_RELEASE_ASSERT( 260 TestEqual(WrappingSubtract(int8_t(-85), int8_t(-73)), int8_t(-12)), 261 "negative minus smaller negative"); 262 MOZ_RELEASE_ASSERT( 263 TestEqual(WrappingSubtract(int8_t(-128), int8_t(127)), int8_t(1)), 264 "underflow to 1"); 265 } 266 267 static void TestWrappingSubtract16() { 268 MOZ_RELEASE_ASSERT(TestEqual(WrappingSubtract(uint16_t(0), uint16_t(32768)), 269 uint16_t(32768)), 270 "zero minus half is half"); 271 MOZ_RELEASE_ASSERT( 272 TestEqual(WrappingSubtract(uint16_t(24389), uint16_t(2682)), 273 uint16_t(21707)), 274 "24389 - 2682 == 21707"); 275 MOZ_RELEASE_ASSERT( 276 TestEqual(WrappingSubtract(uint16_t(0), uint16_t(1)), uint16_t(65535)), 277 "zero underflows to all bits"); 278 MOZ_RELEASE_ASSERT( 279 TestEqual(WrappingSubtract(uint16_t(32768), uint16_t(32767)), 280 uint16_t(1)), 281 "high bit minus all lower bits is one"); 282 MOZ_RELEASE_ASSERT( 283 TestEqual(WrappingSubtract(uint16_t(32768), uint16_t(47582)), 284 uint16_t(50722)), 285 "32768 - 47582 + 65536 is 50722"); 286 287 MOZ_RELEASE_ASSERT( 288 TestEqual(WrappingSubtract(int16_t(0), int16_t(-32768)), int16_t(-32768)), 289 "zero minus high bit wraps to high bit"); 290 MOZ_RELEASE_ASSERT( 291 TestEqual(WrappingSubtract(int16_t(-32766), int16_t(4)), int16_t(32766)), 292 "underflow to positive"); 293 MOZ_RELEASE_ASSERT( 294 TestEqual(WrappingSubtract(int16_t(5), int16_t(-28933)), int16_t(28938)), 295 "5 - -28933 is 28938"); 296 MOZ_RELEASE_ASSERT( 297 TestEqual(WrappingSubtract(int16_t(-23892), int16_t(-12893)), 298 int16_t(-10999)), 299 "negative minus smaller negative"); 300 MOZ_RELEASE_ASSERT( 301 TestEqual(WrappingSubtract(int16_t(-32768), int16_t(32767)), int16_t(1)), 302 "underflow to 1"); 303 } 304 305 static void TestWrappingSubtract32() { 306 MOZ_RELEASE_ASSERT( 307 TestEqual(WrappingSubtract(uint32_t(0), uint32_t(2147483648)), 308 uint32_t(2147483648)), 309 "zero minus half is half"); 310 MOZ_RELEASE_ASSERT( 311 TestEqual(WrappingSubtract(uint32_t(1398742328), uint32_t(714192829)), 312 uint32_t(684549499)), 313 "1398742328 - 714192829 == 684549499"); 314 MOZ_RELEASE_ASSERT(TestEqual(WrappingSubtract(uint32_t(0), uint32_t(1)), 315 uint32_t(4294967295)), 316 "zero underflows to all bits"); 317 MOZ_RELEASE_ASSERT( 318 TestEqual(WrappingSubtract(uint32_t(2147483648), uint32_t(2147483647)), 319 uint32_t(1)), 320 "high bit minus all lower bits is one"); 321 MOZ_RELEASE_ASSERT( 322 TestEqual(WrappingSubtract(uint32_t(2147483648), uint32_t(3146492712)), 323 uint32_t(3295958232)), 324 "2147483648 - 3146492712 + 4294967296 is 3295958232"); 325 326 MOZ_RELEASE_ASSERT( 327 TestEqual(WrappingSubtract(int32_t(0), int32_t(-2147483647 - 1)), 328 int32_t(-2147483647 - 1)), 329 "zero minus high bit wraps to high bit"); 330 MOZ_RELEASE_ASSERT( 331 TestEqual(WrappingSubtract(int32_t(-2147483646), int32_t(4)), 332 int32_t(2147483646)), 333 "underflow to positive"); 334 MOZ_RELEASE_ASSERT( 335 TestEqual(WrappingSubtract(int32_t(257), int32_t(-23947248)), 336 int32_t(23947505)), 337 "257 - -23947248 is 23947505"); 338 MOZ_RELEASE_ASSERT( 339 TestEqual(WrappingSubtract(int32_t(-2147483220), int32_t(-12893)), 340 int32_t(-2147470327)), 341 "negative minus smaller negative"); 342 MOZ_RELEASE_ASSERT( 343 TestEqual(WrappingSubtract(int32_t(-2147483647 - 1), int32_t(2147483647)), 344 int32_t(1)), 345 "underflow to 1"); 346 } 347 348 static void TestWrappingSubtract64() { 349 MOZ_RELEASE_ASSERT( 350 TestEqual(WrappingSubtract(uint64_t(0), uint64_t(9223372036854775808ULL)), 351 uint64_t(9223372036854775808ULL)), 352 "zero minus half is half"); 353 MOZ_RELEASE_ASSERT(TestEqual(WrappingSubtract(uint64_t(70368744177664), 354 uint64_t(3740873592)), 355 uint64_t(70365003304072)), 356 "70368744177664 - 3740873592 == 70365003304072"); 357 MOZ_RELEASE_ASSERT(TestEqual(WrappingSubtract(uint64_t(0), uint64_t(1)), 358 uint64_t(18446744073709551615ULL)), 359 "zero underflows to all bits"); 360 MOZ_RELEASE_ASSERT( 361 TestEqual(WrappingSubtract(uint64_t(9223372036854775808ULL), 362 uint64_t(9223372036854775807ULL)), 363 uint64_t(1)), 364 "high bit minus all lower bits is one"); 365 MOZ_RELEASE_ASSERT( 366 TestEqual(WrappingSubtract(uint64_t(14552598638644786479ULL), 367 uint64_t(3894174382537247221ULL)), 368 uint64_t(10658424256107539258ULL)), 369 "14552598638644786479 - 39763621533397112216 is 10658424256107539258L"); 370 371 MOZ_RELEASE_ASSERT( 372 TestEqual( 373 WrappingSubtract(int64_t(0), int64_t(-9223372036854775807LL - 1)), 374 int64_t(-9223372036854775807LL - 1)), 375 "zero minus high bit wraps to high bit"); 376 MOZ_RELEASE_ASSERT( 377 TestEqual(WrappingSubtract(int64_t(-9223372036854775802LL), int64_t(8)), 378 int64_t(9223372036854775806LL)), 379 "overflow to negative"); 380 MOZ_RELEASE_ASSERT( 381 TestEqual(WrappingSubtract(int64_t(37482739294298742LL), 382 int64_t(-437843573929483498LL)), 383 int64_t(475326313223782240)), 384 "37482739294298742 - -437843573929483498 is 475326313223782240"); 385 MOZ_RELEASE_ASSERT( 386 TestEqual(WrappingSubtract(int64_t(-9127837934058953374LL), 387 int64_t(-4173572032144775807LL)), 388 int64_t(-4954265901914177567LL)), 389 "negative minus smaller negative"); 390 MOZ_RELEASE_ASSERT( 391 TestEqual(WrappingSubtract(int64_t(-9223372036854775807LL - 1), 392 int64_t(9223372036854775807LL)), 393 int64_t(1)), 394 "underflow to 1"); 395 } 396 397 static void TestWrappingSubtract() { 398 TestWrappingSubtract8(); 399 TestWrappingSubtract16(); 400 TestWrappingSubtract32(); 401 TestWrappingSubtract64(); 402 } 403 404 static void TestWrappingMultiply8() { 405 MOZ_RELEASE_ASSERT( 406 TestEqual(WrappingMultiply(uint8_t(0), uint8_t(128)), uint8_t(0)), 407 "zero times anything is zero"); 408 MOZ_RELEASE_ASSERT( 409 TestEqual(WrappingMultiply(uint8_t(128), uint8_t(1)), uint8_t(128)), 410 "1 times anything is anything"); 411 MOZ_RELEASE_ASSERT( 412 TestEqual(WrappingMultiply(uint8_t(2), uint8_t(128)), uint8_t(0)), 413 "2 times high bit overflows, produces zero"); 414 MOZ_RELEASE_ASSERT( 415 TestEqual(WrappingMultiply(uint8_t(8), uint8_t(16)), uint8_t(128)), 416 "multiply that populates the high bit produces that value"); 417 MOZ_RELEASE_ASSERT( 418 TestEqual(WrappingMultiply(uint8_t(127), uint8_t(127)), uint8_t(1)), 419 "multiplying signed maxvals overflows all the way to 1"); 420 421 MOZ_RELEASE_ASSERT( 422 TestEqual(WrappingMultiply(int8_t(0), int8_t(-128)), int8_t(0)), 423 "zero times anything is zero"); 424 MOZ_RELEASE_ASSERT( 425 TestEqual(WrappingMultiply(int8_t(-128), int8_t(1)), int8_t(-128)), 426 "1 times anything is anything"); 427 MOZ_RELEASE_ASSERT( 428 TestEqual(WrappingMultiply(int8_t(2), int8_t(-128)), int8_t(0)), 429 "2 times min overflows, produces zero"); 430 MOZ_RELEASE_ASSERT( 431 TestEqual(WrappingMultiply(int8_t(16), int8_t(24)), int8_t(-128)), 432 "multiply that populates the sign bit produces minval"); 433 MOZ_RELEASE_ASSERT( 434 TestEqual(WrappingMultiply(int8_t(8), int8_t(16)), int8_t(-128)), 435 "multiply that populates the sign bit produces minval"); 436 MOZ_RELEASE_ASSERT( 437 TestEqual(WrappingMultiply(int8_t(127), int8_t(127)), int8_t(1)), 438 "multiplying maxvals overflows all the way to 1"); 439 } 440 441 static void TestWrappingMultiply16() { 442 MOZ_RELEASE_ASSERT( 443 TestEqual(WrappingMultiply(uint16_t(0), uint16_t(32768)), uint16_t(0)), 444 "zero times anything is zero"); 445 MOZ_RELEASE_ASSERT(TestEqual(WrappingMultiply(uint16_t(32768), uint16_t(1)), 446 uint16_t(32768)), 447 "1 times anything is anything"); 448 MOZ_RELEASE_ASSERT( 449 TestEqual(WrappingMultiply(uint16_t(2), uint16_t(32768)), uint16_t(0)), 450 "2 times high bit overflows, produces zero"); 451 MOZ_RELEASE_ASSERT(TestEqual(WrappingMultiply(uint16_t(3), uint16_t(32768)), 452 uint16_t(-32768)), 453 "3 * 32768 - 65536 is 32768"); 454 MOZ_RELEASE_ASSERT( 455 TestEqual(WrappingMultiply(uint16_t(64), uint16_t(512)), uint16_t(32768)), 456 "multiply that populates the high bit produces that value"); 457 MOZ_RELEASE_ASSERT( 458 TestEqual(WrappingMultiply(uint16_t(32767), uint16_t(32767)), 459 uint16_t(1)), 460 "multiplying signed maxvals overflows all the way to 1"); 461 462 MOZ_RELEASE_ASSERT( 463 TestEqual(WrappingMultiply(int16_t(0), int16_t(-32768)), int16_t(0)), 464 "zero times anything is zero"); 465 MOZ_RELEASE_ASSERT( 466 TestEqual(WrappingMultiply(int16_t(-32768), int16_t(1)), int16_t(-32768)), 467 "1 times anything is anything"); 468 MOZ_RELEASE_ASSERT( 469 TestEqual(WrappingMultiply(int16_t(-456), int16_t(123)), int16_t(9448)), 470 "multiply opposite signs, then add 2**16 for the result"); 471 MOZ_RELEASE_ASSERT( 472 TestEqual(WrappingMultiply(int16_t(2), int16_t(-32768)), int16_t(0)), 473 "2 times min overflows, produces zero"); 474 MOZ_RELEASE_ASSERT( 475 TestEqual(WrappingMultiply(int16_t(64), int16_t(512)), int16_t(-32768)), 476 "multiply that populates the sign bit produces minval"); 477 MOZ_RELEASE_ASSERT( 478 TestEqual(WrappingMultiply(int16_t(32767), int16_t(32767)), int16_t(1)), 479 "multiplying maxvals overflows all the way to 1"); 480 } 481 482 static void TestWrappingMultiply32() { 483 MOZ_RELEASE_ASSERT( 484 TestEqual(WrappingMultiply(uint32_t(0), uint32_t(2147483648)), 485 uint32_t(0)), 486 "zero times anything is zero"); 487 MOZ_RELEASE_ASSERT( 488 TestEqual(WrappingMultiply(uint32_t(42), uint32_t(17)), uint32_t(714)), 489 "42 * 17 is 714 without wraparound"); 490 MOZ_RELEASE_ASSERT( 491 TestEqual(WrappingMultiply(uint32_t(2147483648), uint32_t(1)), 492 uint32_t(2147483648)), 493 "1 times anything is anything"); 494 MOZ_RELEASE_ASSERT( 495 TestEqual(WrappingMultiply(uint32_t(2), uint32_t(2147483648)), 496 uint32_t(0)), 497 "2 times high bit overflows, produces zero"); 498 MOZ_RELEASE_ASSERT( 499 TestEqual(WrappingMultiply(uint32_t(8192), uint32_t(262144)), 500 uint32_t(2147483648)), 501 "multiply that populates the high bit produces that value"); 502 MOZ_RELEASE_ASSERT( 503 TestEqual(WrappingMultiply(uint32_t(2147483647), uint32_t(2147483647)), 504 uint32_t(1)), 505 "multiplying signed maxvals overflows all the way to 1"); 506 507 MOZ_RELEASE_ASSERT( 508 TestEqual(WrappingMultiply(int32_t(0), int32_t(-2147483647 - 1)), 509 int32_t(0)), 510 "zero times anything is zero"); 511 MOZ_RELEASE_ASSERT( 512 TestEqual(WrappingMultiply(int32_t(-2147483647 - 1), int32_t(1)), 513 int32_t(-2147483647 - 1)), 514 "1 times anything is anything"); 515 MOZ_RELEASE_ASSERT( 516 TestEqual(WrappingMultiply(int32_t(2), int32_t(-2147483647 - 1)), 517 int32_t(0)), 518 "2 times min overflows, produces zero"); 519 MOZ_RELEASE_ASSERT( 520 TestEqual(WrappingMultiply(int32_t(-7), int32_t(-9)), int32_t(63)), 521 "-7 * -9 is 63, no wraparound needed"); 522 MOZ_RELEASE_ASSERT(TestEqual(WrappingMultiply(int32_t(8192), int32_t(262144)), 523 int32_t(-2147483647 - 1)), 524 "multiply that populates the sign bit produces minval"); 525 MOZ_RELEASE_ASSERT( 526 TestEqual(WrappingMultiply(int32_t(2147483647), int32_t(2147483647)), 527 int32_t(1)), 528 "multiplying maxvals overflows all the way to 1"); 529 } 530 531 static void TestWrappingMultiply64() { 532 MOZ_RELEASE_ASSERT( 533 TestEqual(WrappingMultiply(uint64_t(0), uint64_t(9223372036854775808ULL)), 534 uint64_t(0)), 535 "zero times anything is zero"); 536 MOZ_RELEASE_ASSERT( 537 TestEqual(WrappingMultiply(uint64_t(9223372036854775808ULL), uint64_t(1)), 538 uint64_t(9223372036854775808ULL)), 539 "1 times anything is anything"); 540 MOZ_RELEASE_ASSERT( 541 TestEqual(WrappingMultiply(uint64_t(2), uint64_t(9223372036854775808ULL)), 542 uint64_t(0)), 543 "2 times high bit overflows, produces zero"); 544 MOZ_RELEASE_ASSERT( 545 TestEqual(WrappingMultiply(uint64_t(131072), uint64_t(70368744177664)), 546 uint64_t(9223372036854775808ULL)), 547 "multiply that populates the high bit produces that value"); 548 MOZ_RELEASE_ASSERT(TestEqual(WrappingMultiply(uint64_t(9223372036854775807), 549 uint64_t(9223372036854775807)), 550 uint64_t(1)), 551 "multiplying signed maxvals overflows all the way to 1"); 552 553 MOZ_RELEASE_ASSERT( 554 TestEqual(WrappingMultiply(int64_t(0), int64_t(-9223372036854775807 - 1)), 555 int64_t(0)), 556 "zero times anything is zero"); 557 MOZ_RELEASE_ASSERT( 558 TestEqual(WrappingMultiply(int64_t(-9223372036854775807 - 1), int64_t(1)), 559 int64_t(-9223372036854775807 - 1)), 560 "1 times anything is anything"); 561 MOZ_RELEASE_ASSERT( 562 TestEqual(WrappingMultiply(int64_t(2), int64_t(-9223372036854775807 - 1)), 563 int64_t(0)), 564 "2 times min overflows, produces zero"); 565 MOZ_RELEASE_ASSERT( 566 TestEqual(WrappingMultiply(int64_t(131072), int64_t(70368744177664)), 567 int64_t(-9223372036854775807 - 1)), 568 "multiply that populates the sign bit produces minval"); 569 MOZ_RELEASE_ASSERT(TestEqual(WrappingMultiply(int64_t(9223372036854775807), 570 int64_t(9223372036854775807)), 571 int64_t(1)), 572 "multiplying maxvals overflows all the way to 1"); 573 } 574 575 static void TestWrappingMultiply() { 576 TestWrappingMultiply8(); 577 TestWrappingMultiply16(); 578 TestWrappingMultiply32(); 579 TestWrappingMultiply64(); 580 } 581 582 int main() { 583 TestWrappingAdd(); 584 TestWrappingSubtract(); 585 TestWrappingMultiply(); 586 return 0; 587 }