1// Copyright 2018 The Wuffs Authors. 2// 3// Licensed under the Apache License, Version 2.0 (the "License"); 4// you may not use this file except in compliance with the License. 5// You may obtain a copy of the License at 6// 7// https://www.apache.org/licenses/LICENSE-2.0 8// 9// Unless required by applicable law or agreed to in writing, software 10// distributed under the License is distributed on an "AS IS" BASIS, 11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12// See the License for the specific language governing permissions and 13// limitations under the License. 14 15package interval 16 17import ( 18 "fmt" 19 "math/big" 20 "math/rand" 21 "sort" 22 "strconv" 23 "strings" 24 "testing" 25) 26 27// TestMotivatingExample tests the "motivating example" given in the package 28// doc comment. 29func TestMotivatingExample(tt *testing.T) { 30 i := IntRange{big.NewInt(0), big.NewInt(255)} 31 j := IntRange{big.NewInt(0), big.NewInt(3)} 32 four := IntRange{big.NewInt(4), big.NewInt(4)} 33 got := four.Mul(i).Add(j) 34 want := IntRange{big.NewInt(0), big.NewInt(1023)} 35 if !got.Eq(want) { 36 tt.Fatalf("got %v, want %v", got, want) 37 } 38} 39 40func TestBigIntShifts(tt *testing.T) { 41 // These alternative implementations always take the fallback code path of 42 // bigIntLsh and bigIntRsh. This test checks that those fallback paths give 43 // the same results as *big.Int's Lsh and Rsh methods. There are fallback 44 // and non-fallback code paths in interval.go because those *big.Int 45 // methods aren't applicable if j's value doesn't fit in a uint. 46 47 alternativeBigIntLsh := func(i *big.Int, j *big.Int) *big.Int { 48 // Fallback code path, copy-pasted from interval.go. 49 k := big.NewInt(2) 50 k.Exp(k, j, nil) 51 k.Mul(i, k) 52 return k 53 } 54 55 alternativeBigIntRsh := func(i *big.Int, j *big.Int) *big.Int { 56 // Fallback code path, copy-pasted from interval.go. 57 k := big.NewInt(2) 58 k.Exp(k, j, nil) 59 k.Div(i, k) // This is explicitly Div, not Quo. 60 return k 61 } 62 63 xs := []*big.Int{ 64 big.NewInt(-9), 65 big.NewInt(-8), 66 big.NewInt(-7), 67 68 big.NewInt(-2), 69 big.NewInt(-1), 70 big.NewInt(+0), 71 big.NewInt(+1), 72 big.NewInt(+2), 73 74 big.NewInt(+7), 75 big.NewInt(+8), 76 big.NewInt(+9), 77 } 78 79 ys := []*big.Int{ 80 big.NewInt(+0), 81 big.NewInt(+1), 82 big.NewInt(+2), 83 big.NewInt(+3), 84 big.NewInt(+4), 85 } 86 87 for _, x := range xs { 88 for _, y := range ys { 89 { 90 got := bigIntLsh(x, y) 91 want := alternativeBigIntLsh(x, y) 92 if got.Cmp(want) != 0 { 93 tt.Errorf("%v << %v: got %v, want %v", x, y, got, want) 94 } 95 } 96 97 { 98 got := bigIntRsh(x, y) 99 want := alternativeBigIntRsh(x, y) 100 if got.Cmp(want) != 0 { 101 tt.Errorf("%v >> %v: got %v, want %v", x, y, got, want) 102 } 103 } 104 } 105 } 106} 107 108func trimLeadingSpaces(s string) string { 109 for ; len(s) > 0 && s[0] == ' '; s = s[1:] { 110 } 111 return s 112} 113 114func trimTrailingSpaces(s string) string { 115 for ; len(s) > 0 && s[len(s)-1] == ' '; s = s[:len(s)-1] { 116 } 117 return s 118} 119 120func parseInt(s string) (x *big.Int, remaining string, err error) { 121 s = trimLeadingSpaces(s) 122 i := 0 123 for ; i < len(s); i++ { 124 if c := s[i]; c == ')' || c == ',' || c == ']' { 125 break 126 } 127 } 128 s, remaining = trimTrailingSpaces(s[:i]), s[i:] 129 switch s { 130 case "-∞", "+∞": 131 // No-op. 132 default: 133 n, err := strconv.Atoi(s) 134 if err != nil { 135 return nil, "", fmt.Errorf("parseInt(%q): %v", s, err) 136 } 137 x = big.NewInt(int64(n)) 138 } 139 return x, remaining, nil 140} 141 142// parseInterval parses a string like "[-3, +4] etcetera", returning the 143// interval itself and the remaining string " etcetera". 144// 145// It also parses infinite (unbounded) intervals like "[0, +∞)", and the 146// special syntax "[...empty..]" for an empty interval (one that contains no 147// elements). 148func parseInterval(s string) (x IntRange, remaining string, err error) { 149 const emptySyntax = "[...empty..]" 150 s = trimLeadingSpaces(s) 151 if strings.HasPrefix(s, emptySyntax) { 152 s = s[len(emptySyntax):] 153 return IntRange{big.NewInt(+1), big.NewInt(-1)}, s, nil 154 } 155 156 if s[0] != '(' && s[0] != '[' { 157 return IntRange{}, "", fmt.Errorf("expected '(' or '['") 158 } 159 s = s[1:] 160 x0, s, err := parseInt(s) 161 if err != nil { 162 return IntRange{}, "", err 163 } 164 if s[0] != ',' { 165 return IntRange{}, "", fmt.Errorf("expected ','") 166 } 167 s = s[1:] 168 x1, s, err := parseInt(s) 169 if err != nil { 170 return IntRange{}, "", err 171 } 172 if s[0] != ')' && s[0] != ']' { 173 return IntRange{}, "", fmt.Errorf("expected ')' or ']'") 174 } 175 s = s[1:] 176 if x0 != nil && x1 != nil && x0.Cmp(x1) > 0 { 177 return IntRange{}, "", fmt.Errorf("invalid empty interval") 178 } 179 return IntRange{x0, x1}, s, nil 180} 181 182func TestContainsEtc(tt *testing.T) { 183 testCases := []struct { 184 s string 185 cn uint32 186 cz uint32 187 cp uint32 188 }{ 189 {"<empty-->", 0, 0, 0}, 190 {"<empty0->", 0, 0, 0}, 191 {"<empty+->", 0, 0, 0}, 192 {"<empty+0>", 0, 0, 0}, 193 {"<empty++>", 0, 0, 0}, 194 195 {"(-∞, -1]", 1, 0, 0}, 196 {"(-∞, 0]", 1, 1, 0}, 197 {"(-∞, +1]", 1, 1, 1}, 198 {"(-∞, +∞)", 1, 1, 1}, 199 200 {"[-1, -1]", 1, 0, 0}, 201 {"[-1, 0]", 1, 1, 0}, 202 {"[-1, +1]", 1, 1, 1}, 203 {"[-1, +∞)", 1, 1, 1}, 204 205 {"[ 0, 0]", 0, 1, 0}, 206 {"[ 0, +1]", 0, 1, 1}, 207 {"[ 0, +∞)", 0, 1, 1}, 208 209 {"[+1, +1]", 0, 0, 1}, 210 {"[+1, +∞)", 0, 0, 1}, 211 } 212 213 // eqTestCases is appended to throughout the "range testCases" loop, but it 214 // always contains exactly one empty IntRange. 215 eqTestCases := []IntRange{ 216 empty(), 217 } 218 219 for _, tc := range testCases { 220 x := IntRange{} 221 switch tc.s { 222 case "<empty-->": 223 x = IntRange{big.NewInt(-1), big.NewInt(-2)} 224 case "<empty0->": 225 x = IntRange{big.NewInt(00), big.NewInt(-2)} 226 case "<empty+->": 227 x = IntRange{big.NewInt(+2), big.NewInt(-2)} 228 case "<empty+0>": 229 x = IntRange{big.NewInt(+2), big.NewInt(00)} 230 case "<empty++>": 231 x = IntRange{big.NewInt(+2), big.NewInt(+1)} 232 default: 233 err := error(nil) 234 x, _, err = parseInterval(tc.s) 235 if err != nil { 236 tt.Errorf("%s: %v", tc.s, err) 237 continue 238 } 239 } 240 241 if got, want := x.ContainsNegative(), tc.cn != 0; got != want { 242 tt.Errorf("%s.ContainsNegative(): got %t, want %t", tc.s, got, want) 243 } 244 if got, want := x.ContainsZero(), tc.cz != 0; got != want { 245 tt.Errorf("%s.ContainsZero(): got %t, want %t", tc.s, got, want) 246 } 247 if got, want := x.ContainsPositive(), tc.cp != 0; got != want { 248 tt.Errorf("%s.ContainsPositive(): got %t, want %t", tc.s, got, want) 249 } 250 251 if got, want := x.Empty(), strings.Contains(tc.s, "empty"); got != want { 252 tt.Errorf("%s.Empty(): got %t, want %t", tc.s, got, want) 253 } else if !got { 254 eqTestCases = append(eqTestCases, x) 255 } else if !x.Eq(empty()) { 256 tt.Errorf("%v eq %v: got %t, want %t", x, empty(), got, want) 257 } 258 259 if got, want := x.justZero(), tc.s == "[ 0, 0]"; got != want { 260 tt.Errorf("%s.justZero(): got %t, want %t", tc.s, got, want) 261 } 262 } 263 264 for i, x := range eqTestCases { 265 for j, y := range eqTestCases { 266 got := x.Eq(y) 267 want := i == j 268 if got != want { 269 tt.Errorf("%v eq %v: got %t, want %t", x, y, got, want) 270 } 271 } 272 } 273 274 for _, x := range eqTestCases { 275 neg, pos, negEmpty, hasZero, posEmpty := x.split() 276 if got, want := neg.Empty(), negEmpty; got != want { 277 tt.Errorf("%v: neg.Empty() == %t, negEmpty == %t", x, got, want) 278 } 279 if got, want := !x.ContainsNegative(), negEmpty; got != want { 280 tt.Errorf("%v: !x.ContainsNegative() == %t, negEmpty == %t", x, got, want) 281 } 282 if got, want := x.ContainsZero(), hasZero; got != want { 283 tt.Errorf("%v: x.ContainsZero() == %t, hasZero == %t", x, got, want) 284 } 285 if got, want := !x.ContainsPositive(), posEmpty; got != want { 286 tt.Errorf("%v: !x.ContainsPositive() == %t, posEmpty == %t", x, got, want) 287 } 288 if got, want := pos.Empty(), posEmpty; got != want { 289 tt.Errorf("%v: pos.Empty() == %t, posEmpty == %t", x, got, want) 290 } 291 } 292} 293 294func testBruteForceAgrees(x IntRange, y IntRange, opKey string) error { 295 brute, bruteOK := bruteForce(x, y, opKey) 296 got, gotOK := intOperators[opKey](x, y) 297 if !got.Eq(brute) || gotOK != bruteOK { 298 return fmt.Errorf("got %v, %t, brute force gave %v, %t", got, gotOK, brute, bruteOK) 299 } 300 return nil 301} 302 303func TestBruteForceAgreesSystematically(tt *testing.T) { 304 ints := []*big.Int{ 305 big.NewInt(-7), 306 big.NewInt(-6), 307 big.NewInt(-5), 308 big.NewInt(-4), 309 big.NewInt(-3), 310 big.NewInt(-2), 311 big.NewInt(-1), 312 big.NewInt(+0), 313 big.NewInt(+1), 314 big.NewInt(+2), 315 big.NewInt(+3), 316 big.NewInt(+4), 317 big.NewInt(+5), 318 big.NewInt(+6), 319 big.NewInt(+7), 320 nil, 321 } 322 323 for _, opKey := range intOperatorsKeys { 324 325 for _, x0 := range ints { 326 for _, x1 := range ints { 327 x := IntRange{x0, x1} 328 329 for _, y0 := range ints { 330 for _, y1 := range ints { 331 y := IntRange{y0, y1} 332 333 if err := testBruteForceAgrees(x, y, opKey); err != nil { 334 tt.Fatalf("%v %s %v: %v", x, opKey, y, err) 335 } 336 } 337 } 338 } 339 } 340 } 341} 342 343func TestBruteForceAgreesRandomly(tt *testing.T) { 344 gen := func(rng *rand.Rand) *big.Int { 345 r := rng.Intn(2*riRadius+2) - (riRadius + 1) 346 if r == -(riRadius + 1) { 347 return nil 348 } 349 return big.NewInt(int64(r)) 350 } 351 352 rng := rand.New(rand.NewSource(0)) 353 for _, opKey := range intOperatorsKeys { 354 for i := 0; i < 10000; i++ { 355 x := IntRange{gen(rng), gen(rng)} 356 y := IntRange{gen(rng), gen(rng)} 357 if err := testBruteForceAgrees(x, y, opKey); err != nil { 358 tt.Fatalf("%v %s %v: %v", x, opKey, y, err) 359 } 360 } 361 } 362} 363 364func testOp(tt *testing.T, testCases ...string) { 365 for _, tc := range testCases { 366 if err := testOp1(tc); err != nil { 367 tt.Errorf("%q: %v", tc, err) 368 } 369 } 370} 371 372func testOp1(s string) error { 373 x, s, err := parseInterval(s) 374 if err != nil { 375 return err 376 } 377 s = trimLeadingSpaces(s) 378 379 i := 0 380 for ; i < len(s) && s[i] != ' '; i++ { 381 } 382 opKey, s := s[:i], s[i:] 383 384 y, s, err := parseInterval(s) 385 if err != nil { 386 return err 387 } 388 s = trimLeadingSpaces(s) 389 if !strings.HasPrefix(s, "==") { 390 return fmt.Errorf(`expected "=="`) 391 } 392 s = s[2:] 393 s = trimLeadingSpaces(s) 394 want, wantOK := IntRange{}, false 395 if s == "invalid" { 396 s = "" 397 } else { 398 wantOK = true 399 want, s, err = parseInterval(s) 400 if err != nil { 401 return err 402 } 403 s = trimLeadingSpaces(s) 404 if s != "" { 405 return fmt.Errorf("trailing specification %q", s) 406 } 407 } 408 409 if err := testBruteForceAgrees(x, y, opKey); err != nil { 410 return err 411 } 412 413 got, gotOK := intOperators[opKey](x, y) 414 if !got.Eq(want) || gotOK != wantOK { 415 return fmt.Errorf("package code: got %v, %t, want %v, %t", got, gotOK, want, wantOK) 416 } 417 return nil 418} 419 420var intOperators = map[string]func(IntRange, IntRange) (IntRange, bool){ 421 "+": func(x IntRange, y IntRange) (z IntRange, ok bool) { return x.Add(y), true }, 422 "-": func(x IntRange, y IntRange) (z IntRange, ok bool) { return x.Sub(y), true }, 423 "*": func(x IntRange, y IntRange) (z IntRange, ok bool) { return x.Mul(y), true }, 424 "/": IntRange.Quo, 425 "<<": IntRange.Lsh, 426 ">>": IntRange.Rsh, 427 "&": IntRange.And, 428 "|": IntRange.Or, 429} 430 431var intOperatorsKeys []string 432 433func init() { 434 for k := range intOperators { 435 intOperatorsKeys = append(intOperatorsKeys, k) 436 } 437 sort.Strings(intOperatorsKeys) 438} 439 440func TestOpAdd(tt *testing.T) { 441 testOp(tt, 442 "[ 3, 3] + [ -5, -5] == [ -2, -2]", 443 "[ 3, 3] + [ 0, 0] == [ 3, 3]", 444 "[ 0, 0] + [ -7, 7] == [ -7, 7]", 445 "[ 0, 2] + [ 0, 5] == [ 0, 7]", 446 "[ 3, 6] + [ 10, 15] == [ 13, 21]", 447 "[ 3, +∞) + [ -4, -2] == [ -1, +∞)", 448 "[ 3, +∞) + [ 10, 15] == [ 13, +∞)", 449 "[ 3, +∞) + ( -∞, 15] == ( -∞, +∞)", 450 "[ 3, 6] + ( -∞, 15] == ( -∞, 21]", 451 "[ 3, 6] + ( -∞, +∞) == ( -∞, +∞)", 452 "( -∞, +∞) + ( -∞, +∞) == ( -∞, +∞)", 453 "( -∞, +∞) + [ 1, 2] == ( -∞, +∞)", 454 "( -∞, +∞) + [ 0, 0] == ( -∞, +∞)", 455 "[ 3, 6] + [...empty..] == [...empty..]", 456 "[...empty..] + [ 10, 15] == [...empty..]", 457 "[...empty..] + [...empty..] == [...empty..]", 458 "( -∞, +∞) + [...empty..] == [...empty..]", 459 ) 460} 461 462func TestOpSub(tt *testing.T) { 463 testOp(tt, 464 "[ 3, 3] - [ -5, -5] == [ 8, 8]", 465 "[ 3, 3] - [ 0, 0] == [ 3, 3]", 466 "[ 0, 0] - [ -7, 7] == [ -7, 7]", 467 "[ 0, 2] - [ 0, 5] == [ -5, 2]", 468 "[ 3, 6] - [ 10, 15] == [ -12, -4]", 469 "[ 3, +∞) - [ -4, -2] == [ 5, +∞)", 470 "[ 3, +∞) - [ 10, 15] == [ -12, +∞)", 471 "[ 3, +∞) - ( -∞, 15] == ( -∞, +∞)", 472 "[ 3, 6] - ( -∞, 15] == [ -12, +∞)", 473 "[ 3, 6] - ( -∞, +∞) == ( -∞, +∞)", 474 "( -∞, +∞) - ( -∞, +∞) == ( -∞, +∞)", 475 "( -∞, +∞) - [ 1, 2] == ( -∞, +∞)", 476 "( -∞, +∞) - [ 0, 0] == ( -∞, +∞)", 477 "[ 3, 6] - [...empty..] == [...empty..]", 478 "[...empty..] - [ 10, 15] == [...empty..]", 479 "[...empty..] - [...empty..] == [...empty..]", 480 "( -∞, +∞) - [...empty..] == [...empty..]", 481 ) 482} 483 484func TestOpMul(tt *testing.T) { 485 testOp(tt, 486 "[ 3, 3] * [ -5, -5] == [ -15, -15]", 487 "[ 3, 3] * [ 0, 0] == [ 0, 0]", 488 "[ 0, 0] * [ -7, 7] == [ 0, 0]", 489 "[ 0, 2] * [ 0, 5] == [ 0, 10]", 490 "[ 3, 6] * [ 10, 15] == [ 30, 90]", 491 "[ 3, +∞) * [ -4, -2] == ( -∞, -6]", 492 "[ 3, +∞) * [ 10, 15] == [ 30, +∞)", 493 "[ 3, +∞) * ( -∞, 15] == ( -∞, +∞)", 494 "[ 3, 6] * ( -∞, 15] == ( -∞, 90]", 495 "[ 3, 6] * ( -∞, +∞) == ( -∞, +∞)", 496 "( -∞, +∞) * ( -∞, +∞) == ( -∞, +∞)", 497 "( -∞, +∞) * [ 1, 2] == ( -∞, +∞)", 498 "( -∞, +∞) * [ 0, 0] == [ 0, 0]", 499 "[ 3, 6] * [...empty..] == [...empty..]", 500 "[...empty..] * [ 10, 15] == [...empty..]", 501 "[...empty..] * [...empty..] == [...empty..]", 502 "( -∞, +∞) * [...empty..] == [...empty..]", 503 504 "[ -3, -1] * [ -11, -10] == [ 10, 33]", 505 "[ -3, 0] * [ -11, -10] == [ 0, 33]", 506 "[ -3, 1] * [ -11, -10] == [ -11, 33]", 507 "[ -3, 4] * [ -11, -10] == [ -44, 33]", 508 "[ -1, 4] * [ -11, -10] == [ -44, 11]", 509 "[ 0, 4] * [ -11, -10] == [ -44, 0]", 510 "[ 1, 4] * [ -11, -10] == [ -44, -10]", 511 512 "[ -3, -1] * [ -6, 2] == [ -6, 18]", 513 "[ -3, 0] * [ -6, 2] == [ -6, 18]", 514 "[ -3, 1] * [ -6, 2] == [ -6, 18]", 515 "[ -3, 4] * [ -6, 2] == [ -24, 18]", 516 "[ -1, 4] * [ -6, 2] == [ -24, 8]", 517 "[ 0, 4] * [ -6, 2] == [ -24, 8]", 518 "[ 1, 4] * [ -6, 2] == [ -24, 8]", 519 520 "[ -3, -1] * [ 0, 3] == [ -9, 0]", 521 "[ -3, 0] * [ 0, 3] == [ -9, 0]", 522 "[ -3, 1] * [ 0, 3] == [ -9, 3]", 523 "[ -3, 4] * [ 0, 3] == [ -9, 12]", 524 "[ -1, 4] * [ 0, 3] == [ -3, 12]", 525 "[ 0, 4] * [ 0, 3] == [ 0, 12]", 526 "[ 1, 4] * [ 0, 3] == [ 0, 12]", 527 528 "[ -3, -1] * [ 2, 3] == [ -9, -2]", 529 "[ -3, 0] * [ 2, 3] == [ -9, 0]", 530 "[ -3, 1] * [ 2, 3] == [ -9, 3]", 531 "[ -3, 4] * [ 2, 3] == [ -9, 12]", 532 "[ -1, 4] * [ 2, 3] == [ -3, 12]", 533 "[ 0, 4] * [ 2, 3] == [ 0, 12]", 534 "[ 1, 4] * [ 2, 3] == [ 2, 12]", 535 536 "[ -9, +∞) * [ 2, +∞) == ( -∞, +∞)", 537 "[ -1, +∞) * [ 2, +∞) == ( -∞, +∞)", 538 "[ 0, +∞) * [ 2, +∞) == [ 0, +∞)", 539 "[ 1, +∞) * [ 2, +∞) == [ 2, +∞)", 540 "[ 7, +∞) * [ 2, +∞) == [ 14, +∞)", 541 "[ -1, 1] * ( -∞, +∞) == ( -∞, +∞)", 542 "[ 0, 0] * ( -∞, +∞) == [ 0, 0]", 543 "[ 1, 1] * ( -∞, +∞) == ( -∞, +∞)", 544 ) 545} 546 547func TestOpQuo(tt *testing.T) { 548 testOp(tt, 549 "[ 3, 3] / [ -5, -5] == [ 0, 0]", 550 "[ 3, 3] / [ 0, 0] == invalid", 551 "[ 0, 0] / [ -7, 7] == invalid", 552 "[ 0, 2] / [ 0, 5] == invalid", 553 "[ 3, 6] / [ 10, 15] == [ 0, 0]", 554 "[ 3, +∞) / [ -4, -2] == ( -∞, 0]", 555 "[ 3, +∞) / [ 10, 15] == [ 0, +∞)", 556 "[ 3, +∞) / ( -∞, 15] == invalid", 557 "[ 3, 6] / ( -∞, 15] == invalid", 558 "[ 3, 6] / ( -∞, +∞) == invalid", 559 "( -∞, +∞) / ( -∞, +∞) == invalid", 560 "( -∞, +∞) / [ 1, 2] == ( -∞, +∞)", 561 "( -∞, +∞) / [ 0, 0] == invalid", 562 "[ 3, 6] / [...empty..] == [...empty..]", 563 "[...empty..] / [ 10, 15] == [...empty..]", 564 "[...empty..] / [...empty..] == [...empty..]", 565 "( -∞, +∞) / [...empty..] == [...empty..]", 566 567 "[ 1, 4] / [ -11, -10] == [ 0, 0]", 568 569 "[ 1, 4] / [ -6, 2] == invalid", 570 571 "[ -3, -1] / [ 1, 3] == [ -3, 0]", 572 "[ -3, 0] / [ 1, 3] == [ -3, 0]", 573 "[ -3, 1] / [ 1, 3] == [ -3, 1]", 574 "[ -3, 4] / [ 1, 3] == [ -3, 4]", 575 "[ -1, 4] / [ 1, 3] == [ -1, 4]", 576 "[ 0, 4] / [ 1, 3] == [ 0, 4]", 577 "[ 1, 4] / [ 1, 3] == [ 0, 4]", 578 579 "[ -3, -1] / [ 2, 3] == [ -1, 0]", 580 "[ -3, 0] / [ 2, 3] == [ -1, 0]", 581 "[ -3, 1] / [ 2, 3] == [ -1, 0]", 582 "[ -3, 4] / [ 2, 3] == [ -1, 2]", 583 "[ -1, 4] / [ 2, 3] == [ 0, 2]", 584 "[ 0, 4] / [ 2, 3] == [ 0, 2]", 585 "[ 1, 4] / [ 2, 3] == [ 0, 2]", 586 587 "[ -9, +∞) / [ 2, +∞) == [ -4, +∞)", 588 "[ -1, +∞) / [ 2, +∞) == [ 0, +∞)", 589 "[ 0, +∞) / [ 2, +∞) == [ 0, +∞)", 590 "[ 1, +∞) / [ 2, +∞) == [ 0, +∞)", 591 "[ 7, +∞) / [ 2, +∞) == [ 0, +∞)", 592 "[ -1, 1] / ( -∞, +∞) == invalid", 593 "[ 0, 0] / ( -∞, +∞) == invalid", 594 "[ 1, 1] / ( -∞, +∞) == invalid", 595 ) 596} 597 598func TestOpLsh(tt *testing.T) { 599 testOp(tt, 600 "[ 3, 3] << [ -5, -5] == invalid", 601 "[ 3, 3] << [ 0, 0] == [ 3, 3]", 602 "[ 0, 0] << [ -7, 7] == invalid", 603 "[ 0, 2] << [ 0, 5] == [ 0, 64]", 604 "[ 3, 6] << [ 10, 15] == [3072, 196608]", 605 "[ 3, +∞) << [ -4, -2] == invalid", 606 "[ 3, +∞) << [ 10, 15] == [3072, +∞)", 607 "[ 3, +∞) << ( -∞, 15] == invalid", 608 "[ 3, 6] << ( -∞, 15] == invalid", 609 "[ 3, 6] << ( -∞, +∞) == invalid", 610 "( -∞, +∞) << ( -∞, +∞) == invalid", 611 "( -∞, +∞) << [ 1, 2] == ( -∞, +∞)", 612 "( -∞, +∞) << [ 0, 0] == ( -∞, +∞)", 613 "[ 3, 6] << [...empty..] == [...empty..]", 614 "[...empty..] << [ 10, 15] == [...empty..]", 615 "[...empty..] << [...empty..] == [...empty..]", 616 "( -∞, +∞) << [...empty..] == [...empty..]", 617 618 "[ 1, 4] << [ -11, -10] == invalid", 619 620 "[ 1, 4] << [ -6, 2] == invalid", 621 622 "[ -3, -1] << [ 0, 3] == [ -24, -1]", 623 "[ -3, 0] << [ 0, 3] == [ -24, 0]", 624 "[ -3, 1] << [ 0, 3] == [ -24, 8]", 625 "[ -3, 4] << [ 0, 3] == [ -24, 32]", 626 "[ -1, 4] << [ 0, 3] == [ -8, 32]", 627 "[ 0, 4] << [ 0, 3] == [ 0, 32]", 628 "[ 1, 4] << [ 0, 3] == [ 1, 32]", 629 630 "[ -3, -1] << [ 2, 3] == [ -24, -4]", 631 "[ -3, 0] << [ 2, 3] == [ -24, 0]", 632 "[ -3, 1] << [ 2, 3] == [ -24, 8]", 633 "[ -3, 4] << [ 2, 3] == [ -24, 32]", 634 "[ -1, 4] << [ 2, 3] == [ -8, 32]", 635 "[ 0, 4] << [ 2, 3] == [ 0, 32]", 636 "[ 1, 4] << [ 2, 3] == [ 4, 32]", 637 638 "[ -9, +∞) << [ 2, +∞) == ( -∞, +∞)", 639 "[ -1, +∞) << [ 2, +∞) == ( -∞, +∞)", 640 "[ 0, +∞) << [ 2, +∞) == [ 0, +∞)", 641 "[ 1, +∞) << [ 2, +∞) == [ 4, +∞)", 642 "[ 7, +∞) << [ 2, +∞) == [ 28, +∞)", 643 "[ -1, 1] << ( -∞, +∞) == invalid", 644 "[ 0, 0] << ( -∞, +∞) == invalid", 645 "[ 1, 1] << ( -∞, +∞) == invalid", 646 ) 647} 648 649func TestOpRsh(tt *testing.T) { 650 testOp(tt, 651 "[ 3, 3] >> [ -5, -5] == invalid", 652 "[ 3, 3] >> [ 0, 0] == [ 3, 3]", 653 "[ 0, 0] >> [ -7, 7] == invalid", 654 "[ 0, 2] >> [ 0, 5] == [ 0, 2]", 655 "[ 3, 6] >> [ 10, 15] == [ 0, 0]", 656 "[ 3, +∞) >> [ -4, -2] == invalid", 657 "[ 3, +∞) >> [ 10, 15] == [ 0, +∞)", 658 "[ 3, +∞) >> ( -∞, 15] == invalid", 659 "[ 3, 6] >> ( -∞, 15] == invalid", 660 "[ 3, 6] >> ( -∞, +∞) == invalid", 661 "( -∞, +∞) >> ( -∞, +∞) == invalid", 662 "( -∞, +∞) >> [ 1, 2] == ( -∞, +∞)", 663 "( -∞, +∞) >> [ 0, 0] == ( -∞, +∞)", 664 "[ 3, 6] >> [...empty..] == [...empty..]", 665 "[...empty..] >> [ 10, 15] == [...empty..]", 666 "[...empty..] >> [...empty..] == [...empty..]", 667 "( -∞, +∞) >> [...empty..] == [...empty..]", 668 669 "[ 1, 4] >> [ -11, -10] == invalid", 670 671 "[ 1, 4] >> [ -6, 2] == invalid", 672 673 "[ -3, -1] >> [ 0, 3] == [ -3, -1]", 674 "[ -3, 0] >> [ 0, 3] == [ -3, 0]", 675 "[ -3, 1] >> [ 0, 3] == [ -3, 1]", 676 "[ -3, 4] >> [ 0, 3] == [ -3, 4]", 677 "[ -1, 4] >> [ 0, 3] == [ -1, 4]", 678 "[ 0, 4] >> [ 0, 3] == [ 0, 4]", 679 "[ 1, 4] >> [ 0, 3] == [ 0, 4]", 680 681 "[ -3, -1] >> [ 1, 3] == [ -2, -1]", 682 "[ -3, 0] >> [ 1, 3] == [ -2, 0]", 683 "[ -3, 1] >> [ 1, 3] == [ -2, 0]", 684 "[ -3, 4] >> [ 1, 3] == [ -2, 2]", 685 "[ -1, 4] >> [ 1, 3] == [ -1, 2]", 686 "[ 0, 4] >> [ 1, 3] == [ 0, 2]", 687 "[ 1, 4] >> [ 1, 3] == [ 0, 2]", 688 689 "[ -9, +∞) >> [ 2, +∞) == [ -3, +∞)", 690 "[ -1, +∞) >> [ 2, +∞) == [ -1, +∞)", 691 "[ 0, +∞) >> [ 2, +∞) == [ 0, +∞)", 692 "[ 1, +∞) >> [ 2, +∞) == [ 0, +∞)", 693 "[ 7, +∞) >> [ 2, +∞) == [ 0, +∞)", 694 "[ -1, 1] >> ( -∞, +∞) == invalid", 695 "[ 0, 0] >> ( -∞, +∞) == invalid", 696 "[ 1, 1] >> ( -∞, +∞) == invalid", 697 ) 698} 699 700func TestOpAnd(tt *testing.T) { 701 testOp(tt, 702 "[ 3, 3] & [ -5, -5] == invalid", 703 "[ 3, 3] & [ 0, 0] == [ 0, 0]", 704 "[ 0, 0] & [ -7, 7] == invalid", 705 "[ 0, 2] & [ 0, 5] == [ 0, 2]", 706 "[ 3, 6] & [ 10, 15] == [ 0, 6]", 707 "[ 3, +∞) & [ -4, -2] == invalid", 708 "[ 3, +∞) & [ 10, 15] == [ 0, 15]", 709 "[ 3, +∞) & ( -∞, 15] == invalid", 710 "[ 3, 6] & ( -∞, 15] == invalid", 711 "[ 3, 6] & ( -∞, +∞) == invalid", 712 "( -∞, +∞) & ( -∞, +∞) == invalid", 713 "( -∞, +∞) & [ 1, 2] == invalid", 714 "( -∞, +∞) & [ 0, 0] == invalid", 715 "[ 3, 6] & [...empty..] == [...empty..]", 716 "[...empty..] & [ 10, 15] == [...empty..]", 717 "[...empty..] & [...empty..] == [...empty..]", 718 "( -∞, +∞) & [...empty..] == [...empty..]", 719 720 "[ 1, 4] & [ -11, -10] == invalid", 721 722 "[ 1, 4] & [ -6, 2] == invalid", 723 724 "[ -3, -1] & [ 0, 3] == invalid", 725 "[ -1, 4] & [ 0, 3] == invalid", 726 "[ 0, 4] & [ 0, 3] == [ 0, 3]", 727 "[ 1, 4] & [ 0, 3] == [ 0, 3]", 728 729 "[ -3, -1] & [ 2, 3] == invalid", 730 "[ -1, 4] & [ 2, 3] == invalid", 731 "[ 0, 4] & [ 2, 3] == [ 0, 3]", 732 "[ 1, 4] & [ 2, 3] == [ 0, 3]", 733 734 "[ -9, +∞) & [ 2, +∞) == invalid", 735 "[ -1, +∞) & [ 2, +∞) == invalid", 736 "[ 0, +∞) & [ 2, +∞) == [ 0, +∞)", 737 "[ 1, +∞) & [ 2, +∞) == [ 0, +∞)", 738 "[ 7, +∞) & [ 2, +∞) == [ 0, +∞)", 739 "[ -1, 1] & ( -∞, +∞) == invalid", 740 "[ 0, 0] & ( -∞, +∞) == invalid", 741 "[ 1, 1] & ( -∞, +∞) == invalid", 742 743 "[ 1, 3] & [ 4, 9] == [ 0, 3]", 744 "[ 3, 4] & [ 5, 6] == [ 1, 4]", 745 "[ 4, 5] & [ 6, 7] == [ 4, 5]", 746 "[ 7, 7] & [ 12, 14] == [ 4, 6]", 747 748 "[ 5, 6] & [ 6, 7] == [ 4, 6]", 749 "[ 5, 6] & [ 6, 8] == [ 0, 6]", 750 "[ 5, 9] & [ 6, 8] == [ 0, 8]", 751 "[ 5, 9] & [ 6, 9] == [ 0, 9]", 752 753 "[ 5, 6] & [ 3, +∞) == [ 0, 6]", 754 "[ 5, 9] & [ 3, +∞) == [ 0, 9]", 755 "[ 5, 6] & [ 7, +∞) == [ 0, 6]", 756 "[ 5, 9] & [ 7, +∞) == [ 0, 9]", 757 "[ 5, 6] & [ 8, +∞) == [ 0, 6]", 758 "[ 5, 9] & [ 8, +∞) == [ 0, 9]", 759 "[ 5, 6] & [ 9, +∞) == [ 0, 6]", 760 "[ 5, 9] & [ 9, +∞) == [ 0, 9]", 761 "[ 5, 6] & [ 12, +∞) == [ 0, 6]", 762 "[ 5, 9] & [ 12, +∞) == [ 0, 9]", 763 ) 764} 765 766func TestOpOr(tt *testing.T) { 767 testOp(tt, 768 "[ 3, 3] | [ -5, -5] == invalid", 769 "[ 3, 3] | [ 0, 0] == [ 3, 3]", 770 "[ 0, 0] | [ -7, 7] == invalid", 771 "[ 0, 2] | [ 0, 5] == [ 0, 7]", 772 "[ 3, 6] | [ 10, 15] == [ 11, 15]", 773 "[ 3, +∞) | [ -4, -2] == invalid", 774 "[ 3, +∞) | [ 10, 15] == [ 10, +∞)", 775 "[ 3, +∞) | ( -∞, 15] == invalid", 776 "[ 3, 6] | ( -∞, 15] == invalid", 777 "[ 3, 6] | ( -∞, +∞) == invalid", 778 "( -∞, +∞) | ( -∞, +∞) == invalid", 779 "( -∞, +∞) | [ 1, 2] == invalid", 780 "( -∞, +∞) | [ 0, 0] == invalid", 781 "[ 3, 6] | [...empty..] == [...empty..]", 782 "[...empty..] | [ 10, 15] == [...empty..]", 783 "[...empty..] | [...empty..] == [...empty..]", 784 "( -∞, +∞) | [...empty..] == [...empty..]", 785 786 "[ 1, 4] | [ -11, -10] == invalid", 787 788 "[ 1, 4] | [ -6, 2] == invalid", 789 790 "[ -3, -1] | [ 0, 3] == invalid", 791 "[ -1, 4] | [ 0, 3] == invalid", 792 "[ 0, 4] | [ 0, 3] == [ 0, 7]", 793 "[ 1, 4] | [ 0, 3] == [ 1, 7]", 794 795 "[ -3, -1] | [ 2, 3] == invalid", 796 "[ -1, 4] | [ 2, 3] == invalid", 797 "[ 0, 4] | [ 2, 3] == [ 2, 7]", 798 "[ 1, 4] | [ 2, 3] == [ 2, 7]", 799 800 "[ -9, +∞) | [ 2, +∞) == invalid", 801 "[ -1, +∞) | [ 2, +∞) == invalid", 802 "[ 0, +∞) | [ 2, +∞) == [ 2, +∞)", 803 "[ 1, +∞) | [ 2, +∞) == [ 2, +∞)", 804 "[ 7, +∞) | [ 2, +∞) == [ 7, +∞)", 805 "[ -1, 1] | ( -∞, +∞) == invalid", 806 "[ 0, 0] | ( -∞, +∞) == invalid", 807 "[ 1, 1] | ( -∞, +∞) == invalid", 808 809 "[ 1, 3] | [ 4, 9] == [ 5, 11]", 810 "[ 3, 4] | [ 5, 6] == [ 5, 7]", 811 "[ 4, 5] | [ 6, 7] == [ 6, 7]", 812 "[ 7, 7] | [ 12, 14] == [ 15, 15]", 813 814 "[ 5, 6] | [ 6, 7] == [ 6, 7]", 815 "[ 5, 6] | [ 6, 8] == [ 6, 14]", 816 "[ 5, 9] | [ 6, 8] == [ 6, 15]", 817 "[ 5, 9] | [ 6, 9] == [ 6, 15]", 818 819 "[ 5, 6] | [ 3, +∞) == [ 5, +∞)", 820 "[ 5, 9] | [ 3, +∞) == [ 5, +∞)", 821 "[ 5, 6] | [ 7, +∞) == [ 7, +∞)", 822 "[ 5, 9] | [ 7, +∞) == [ 7, +∞)", 823 "[ 5, 6] | [ 8, +∞) == [ 13, +∞)", 824 "[ 5, 9] | [ 8, +∞) == [ 8, +∞)", 825 "[ 5, 6] | [ 9, +∞) == [ 13, +∞)", 826 "[ 5, 9] | [ 9, +∞) == [ 9, +∞)", 827 "[ 5, 6] | [ 12, +∞) == [ 13, +∞)", 828 "[ 5, 9] | [ 12, +∞) == [ 12, +∞)", 829 ) 830} 831