• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
15// ----------------
16
17// Package interval provides interval arithmetic on big integers. Big means
18// arbitrary-precision, as per the standard math/big package.
19//
20// For example, if x is in the interval [3, 6] and y is in the interval [10,
21// 15] then x+y is in the interval [13, 21].
22//
23// Such intervals may have infinite bounds. For example, if x is in the
24// interval [3, +∞) and y is in the interval [-4, -2], then x*y is in the
25// interval (-∞, -6].
26//
27// As a motivating example, if a compiler knows that the integer-typed
28// variables i and j are in the intervals [0, 255] and [0, 3], and that the
29// array a has 1024 elements, then it can prove that the array-index expression
30// a[4*i + j] is memory-safe without needing an at-runtime bounds check.
31//
32// This package depends only on the standard math/big package.
33package interval
34
35import (
36	"math/big"
37)
38
39var (
40	one = big.NewInt(1)
41)
42
43func bigIntMul(i *big.Int, j *big.Int) *big.Int { return big.NewInt(0).Mul(i, j) }
44func bigIntQuo(i *big.Int, j *big.Int) *big.Int { return big.NewInt(0).Quo(i, j) }
45
46func bigIntLsh(i *big.Int, j *big.Int) *big.Int {
47	if j.IsUint64() {
48		if u := j.Uint64(); u <= 0xFFFFFFFF {
49			return big.NewInt(0).Lsh(i, uint(u))
50		}
51	}
52
53	// Fallback code path, copy-pasted to interval_test.go.
54	k := big.NewInt(2)
55	k.Exp(k, j, nil)
56	k.Mul(i, k)
57	return k
58}
59
60func bigIntRsh(i *big.Int, j *big.Int) *big.Int {
61	if j.IsUint64() {
62		if u := j.Uint64(); u <= 0xFFFFFFFF {
63			return big.NewInt(0).Rsh(i, uint(u))
64		}
65	}
66
67	// Fallback code path, copy-pasted to interval_test.go.
68	k := big.NewInt(2)
69	k.Exp(k, j, nil)
70	k.Div(i, k) // This is explicitly Div, not Quo.
71	return k
72}
73
74// biggerInt is either a non-nil *big.Int or ±∞.
75type biggerInt struct {
76	// extra being less than or greater than 0 means that the biggerInt is -∞
77	// or +∞ respectively. extra being zero means that the biggerInt is i,
78	// which should be a non-nil pointer.
79	extra int32
80	i     *big.Int
81}
82
83type biggerIntPair [2]biggerInt
84
85// newBiggerIntPair returns a pair of biggerInt values, the first being +∞
86// and the second being -∞.
87func newBiggerIntPair() biggerIntPair { return biggerIntPair{{extra: +1}, {extra: -1}} }
88
89// lowerMin sets x[0] to min(x[0], y).
90func (x *biggerIntPair) lowerMin(y biggerInt) {
91	if x[0].extra > 0 || y.extra < 0 ||
92		(x[0].extra == 0 && y.extra == 0 && x[0].i.Cmp(y.i) > 0) {
93		x[0] = y
94	}
95}
96
97// raiseMax sets x[1] to max(x[1], y).
98func (x *biggerIntPair) raiseMax(y biggerInt) {
99	if x[1].extra < 0 || y.extra > 0 ||
100		(x[1].extra == 0 && y.extra == 0 && x[1].i.Cmp(y.i) < 0) {
101		x[1] = y
102	}
103}
104
105func (x *biggerIntPair) toIntRange() IntRange {
106	if x[0].extra > 0 || x[1].extra < 0 {
107		return empty()
108	}
109	return IntRange{x[0].i, x[1].i}
110}
111
112func (x *biggerIntPair) fromIntRange(y IntRange) {
113	if y[0] != nil {
114		x[0] = biggerInt{i: big.NewInt(0).Set(y[0])}
115	} else {
116		x[0] = biggerInt{extra: -1}
117	}
118	if y[1] != nil {
119		x[1] = biggerInt{i: big.NewInt(0).Set(y[1])}
120	} else {
121		x[1] = biggerInt{extra: +1}
122	}
123}
124
125// IntRange is an integer interval. The array elements are the minimum and
126// maximum values, inclusive (if non-nil) on both ends. A nil element means
127// unbounded: negative or positive infinity.
128//
129// The zero value (zero in the Go sense, not in the integer sense) is a valid,
130// infinitely sized interval, unbounded at both ends.
131//
132// A subtle point is that an interval's minimum or maximum can be infinite, but
133// if an integer value i is known to be within such an interval, i's possible
134// values are arbitrarily large but not infinite. Specifically, 0*i is
135// unambiguously always equal to 0.
136//
137// It is also valid for the first element to be greater than the second
138// element. This represents an empty interval. There is more than one
139// representation of an empty interval.
140//
141// "Int" abbreviates "Integer" (the same as for big.Int), not "Interval".
142// Similarly, we use "Range" instead of "Interval" to avoid unnecessary
143// confusion, even though this type is indeed an integer interval.
144type IntRange [2]*big.Int
145
146// String returns a string representation of x.
147func (x IntRange) String() string {
148	if x.Empty() {
149		return "<empty>"
150	}
151	buf := []byte(nil)
152	if x[0] == nil {
153		buf = append(buf, "(-∞, "...)
154	} else {
155		buf = append(buf, '[')
156		buf = x[0].Append(buf, 10)
157		buf = append(buf, ".."...)
158	}
159	if x[1] == nil {
160		buf = append(buf, "+∞)"...)
161	} else {
162		buf = x[1].Append(buf, 10)
163		buf = append(buf, ']')
164	}
165	return string(buf)
166}
167
168// empty returns an empty IntRange: one that contains no elements.
169func empty() IntRange {
170	return IntRange{big.NewInt(+1), big.NewInt(-1)}
171}
172
173// ContainsNegative returns whether x contains at least one negative value.
174func (x IntRange) ContainsNegative() bool {
175	if x[0] == nil {
176		return true
177	}
178	if x[0].Sign() >= 0 {
179		return false
180	}
181	return x[1] == nil || x[0].Cmp(x[1]) <= 0
182}
183
184// ContainsPositive returns whether x contains at least one positive value.
185func (x IntRange) ContainsPositive() bool {
186	if x[1] == nil {
187		return true
188	}
189	if x[1].Sign() <= 0 {
190		return false
191	}
192	return x[0] == nil || x[0].Cmp(x[1]) <= 0
193}
194
195// ContainsZero returns whether x contains zero.
196func (x IntRange) ContainsZero() bool {
197	return (x[0] == nil || x[0].Sign() <= 0) &&
198		(x[1] == nil || x[1].Sign() >= 0)
199}
200
201// ContainsInt returns whether x contains i.
202func (x IntRange) ContainsInt(i *big.Int) bool {
203	return (x[0] == nil || x[0].Cmp(i) <= 0) &&
204		(x[1] == nil || x[1].Cmp(i) >= 0)
205}
206
207// ContainsIntRange returns whether x contains every element of y.
208//
209// It returns true if y is empty.
210func (x IntRange) ContainsIntRange(y IntRange) bool {
211	if y.Empty() {
212		return true
213	}
214	if (x[0] != nil) && (y[0] == nil || x[0].Cmp(y[0]) > 0) {
215		return false
216	}
217	if (x[1] != nil) && (y[1] == nil || x[1].Cmp(y[1]) < 0) {
218		return false
219	}
220	return true
221}
222
223// Eq returns whether x equals y.
224func (x IntRange) Eq(y IntRange) bool {
225	if xe, ye := x.Empty(), y.Empty(); xe || ye {
226		return xe == ye
227	}
228	if x0, y0 := x[0] != nil, y[0] != nil; x0 != y0 {
229		return false
230	} else if x0 && x[0].Cmp(y[0]) != 0 {
231		return false
232	}
233	if x1, y1 := x[1] != nil, y[1] != nil; x1 != y1 {
234		return false
235	} else if x1 && x[1].Cmp(y[1]) != 0 {
236		return false
237	}
238	return true
239}
240
241// Empty returns whether x is empty.
242func (x IntRange) Empty() bool {
243	return x[0] != nil && x[1] != nil && x[0].Cmp(x[1]) > 0
244}
245
246// justZero returns whether x is the [0, 0] interval, containing exactly one
247// element: the integer zero.
248func (x IntRange) justZero() bool {
249	return x[0] != nil && x[1] != nil && x[0].Sign() == 0 && x[1].Sign() == 0
250}
251
252// split splits x into negative, zero and positive sub-intervals. The IntRange
253// values returned may be empty, which means that x does not contain any
254// negative or positive elements.
255func (x IntRange) split() (neg IntRange, pos IntRange, negEmpty bool, hasZero bool, posEmpty bool) {
256	if x[0] != nil && x[0].Sign() > 0 {
257		return empty(), x, true, false, x.Empty()
258	}
259	if x[1] != nil && x[1].Sign() < 0 {
260		return x, empty(), x.Empty(), false, true
261	}
262
263	neg[0] = x[0]
264	neg[1] = big.NewInt(-1)
265	if x[1] != nil && x[1].Cmp(neg[1]) < 0 {
266		neg[1] = x[1]
267	}
268
269	pos[0] = big.NewInt(+1)
270	if x[0] != nil && x[0].Cmp(pos[0]) > 0 {
271		pos[0] = x[0]
272	}
273	pos[1] = x[1]
274
275	return neg, pos, neg.Empty(), x.ContainsZero(), pos.Empty()
276}
277
278// Add returns z = x + y.
279func (x IntRange) Add(y IntRange) (z IntRange) {
280	if x.Empty() || y.Empty() {
281		return empty()
282	}
283	if x[0] != nil && y[0] != nil {
284		z[0] = big.NewInt(0).Add(x[0], y[0])
285	}
286	if x[1] != nil && y[1] != nil {
287		z[1] = big.NewInt(0).Add(x[1], y[1])
288	}
289	return z
290}
291
292// Sub returns z = x - y.
293func (x IntRange) Sub(y IntRange) (z IntRange) {
294	if x.Empty() || y.Empty() {
295		return empty()
296	}
297	if x[0] != nil && y[1] != nil && (x[1] != nil || y[0] != nil) {
298		z[0] = big.NewInt(0).Sub(x[0], y[1])
299	}
300	if x[1] != nil && y[0] != nil && (x[0] != nil || y[1] != nil) {
301		z[1] = big.NewInt(0).Sub(x[1], y[0])
302	}
303	return z
304}
305
306// Mul returns z = x * y.
307func (x IntRange) Mul(y IntRange) (z IntRange) {
308	return x.mulLsh(y, false)
309}
310
311// Lsh returns z = x << y.
312//
313// ok is false (and z will be IntRange{nil, nil}) if x is non-empty and y
314// contains at least one negative value, as it's invalid to shift by a negative
315// number. Otherwise, ok is true.
316func (x IntRange) Lsh(y IntRange) (z IntRange, ok bool) {
317	if !x.Empty() && y.ContainsNegative() {
318		return IntRange{}, false
319	}
320	return x.mulLsh(y, true), true
321}
322
323func (x IntRange) mulLsh(y IntRange, shift bool) (z IntRange) {
324	if x.Empty() || y.Empty() {
325		return empty()
326	}
327	if x.justZero() || (!shift && y.justZero()) {
328		return IntRange{big.NewInt(0), big.NewInt(0)}
329	}
330
331	combine := bigIntMul
332	if shift {
333		combine = bigIntLsh
334	}
335
336	ret := newBiggerIntPair()
337
338	// Split x and y into negative, zero and positive parts.
339	negX, posX, negXEmpty, zeroX, posXEmpty := x.split()
340	negY, posY, negYEmpty, zeroY, posYEmpty := y.split()
341
342	if zeroY && shift {
343		ret.fromIntRange(x)
344	} else if (zeroY && !shift) || zeroX {
345		ret[0] = biggerInt{i: big.NewInt(0)}
346		ret[1] = biggerInt{i: big.NewInt(0)}
347	}
348
349	if !negXEmpty {
350		if !negYEmpty {
351			// x is negative and y is negative, so x op y is positive.
352			//
353			// If op is << instead of * then we have previously checked that y
354			// is non-negative, so this should be unreachable.
355			ret.lowerMin(biggerInt{i: combine(negX[1], negY[1])})
356			if negX[0] == nil || negY[0] == nil {
357				ret.raiseMax(biggerInt{extra: +1})
358			} else {
359				ret.raiseMax(biggerInt{i: combine(negX[0], negY[0])})
360			}
361		}
362
363		if !posYEmpty {
364			// x is negative and y is positive, so x op y is negative.
365			if negX[0] == nil || posY[1] == nil {
366				ret.lowerMin(biggerInt{extra: -1})
367			} else {
368				ret.lowerMin(biggerInt{i: combine(negX[0], posY[1])})
369			}
370			ret.raiseMax(biggerInt{i: combine(negX[1], posY[0])})
371		}
372	}
373
374	if !posXEmpty {
375		if !negYEmpty {
376			// x is positive and y is negative, so x op y is negative.
377			//
378			// If op is << instead of * then we have previously checked that y
379			// is non-negative, so this should be unreachable.
380			if posX[1] == nil || negY[0] == nil {
381				ret.lowerMin(biggerInt{extra: -1})
382			} else {
383				ret.lowerMin(biggerInt{i: combine(posX[1], negY[0])})
384			}
385			ret.raiseMax(biggerInt{i: combine(posX[0], negY[1])})
386		}
387
388		if !posYEmpty {
389			// x is positive and y is positive, so x op y is positive.
390			ret.lowerMin(biggerInt{i: combine(posX[0], posY[0])})
391			if posX[1] == nil || posY[1] == nil {
392				ret.raiseMax(biggerInt{extra: +1})
393			} else {
394				ret.raiseMax(biggerInt{i: combine(posX[1], posY[1])})
395			}
396		}
397	}
398
399	return ret.toIntRange()
400}
401
402// Quo returns z = x / y. Like the big.Int.Quo method (and unlike the
403// big.Int.Div method), it truncates towards zero.
404//
405// ok is false (and z will be IntRange{nil, nil}) if x is non-empty and y
406// contains zero, as it's invalid to divide by zero. Otherwise, ok is true.
407func (x IntRange) Quo(y IntRange) (z IntRange, ok bool) {
408	if x.Empty() || y.Empty() {
409		return empty(), true
410	}
411	if y.ContainsZero() {
412		return IntRange{}, false
413	}
414	if x.justZero() {
415		return IntRange{big.NewInt(0), big.NewInt(0)}, true
416	}
417
418	ret := newBiggerIntPair()
419
420	// Split x and y into negative, zero and positive parts.
421	negX, posX, negXEmpty, zeroX, posXEmpty := x.split()
422	negY, posY, negYEmpty, _, posYEmpty := y.split()
423
424	if zeroX {
425		ret[0] = biggerInt{i: big.NewInt(0)}
426		ret[1] = biggerInt{i: big.NewInt(0)}
427	}
428
429	if !negXEmpty {
430		if !negYEmpty {
431			// x is negative and y is negative, so x / y is non-negative.
432			if negX[0] == nil {
433				ret.raiseMax(biggerInt{extra: +1})
434			} else {
435				ret.raiseMax(biggerInt{i: bigIntQuo(negX[0], negY[1])})
436			}
437			if negY[0] == nil {
438				ret.lowerMin(biggerInt{i: big.NewInt(0)})
439			} else {
440				ret.lowerMin(biggerInt{i: bigIntQuo(negX[1], negY[0])})
441			}
442		}
443
444		if !posYEmpty {
445			// x is negative and y is positive, so x / y is non-positive.
446			if negX[0] == nil {
447				ret.lowerMin(biggerInt{extra: -1})
448			} else {
449				ret.lowerMin(biggerInt{i: bigIntQuo(negX[0], posY[0])})
450			}
451			if posY[1] == nil {
452				ret.raiseMax(biggerInt{i: big.NewInt(0)})
453			} else {
454				ret.raiseMax(biggerInt{i: bigIntQuo(negX[1], posY[1])})
455			}
456		}
457	}
458
459	if !posXEmpty {
460		if !negYEmpty {
461			// x is positive and y is negative, so x / y is non-positive.
462			if posX[1] == nil {
463				ret.lowerMin(biggerInt{extra: -1})
464			} else {
465				ret.lowerMin(biggerInt{i: bigIntQuo(posX[1], negY[1])})
466			}
467			if negY[0] == nil {
468				ret.raiseMax(biggerInt{i: big.NewInt(0)})
469			} else {
470				ret.raiseMax(biggerInt{i: bigIntQuo(posX[0], negY[0])})
471			}
472		}
473
474		if !posYEmpty {
475			// x is positive and y is positive, so x / y is non-negative.
476			if posX[1] == nil {
477				ret.raiseMax(biggerInt{extra: +1})
478			} else {
479				ret.raiseMax(biggerInt{i: bigIntQuo(posX[1], posY[0])})
480			}
481			if posY[1] == nil {
482				ret.lowerMin(biggerInt{i: big.NewInt(0)})
483			} else {
484				ret.lowerMin(biggerInt{i: bigIntQuo(posX[0], posY[1])})
485			}
486		}
487	}
488
489	return ret.toIntRange(), true
490}
491
492// Rsh returns z = x >> y.
493//
494// ok is false (and z will be IntRange{nil, nil}) if x is non-empty and y
495// contains at least one negative value, as it's invalid to shift by a negative
496// number. Otherwise, ok is true.
497func (x IntRange) Rsh(y IntRange) (z IntRange, ok bool) {
498	if x.Empty() || y.Empty() {
499		return empty(), true
500	}
501	if y.ContainsNegative() {
502		return IntRange{}, false
503	}
504	if x.justZero() {
505		return IntRange{big.NewInt(0), big.NewInt(0)}, true
506	}
507
508	ret := newBiggerIntPair()
509
510	// Split x and y into negative and zero-or-positive parts.
511	negX, posX, negXEmpty, zeroX, posXEmpty := x.split()
512
513	if zeroX {
514		ret[0] = biggerInt{i: big.NewInt(0)}
515		ret[1] = biggerInt{i: big.NewInt(0)}
516	}
517
518	if !negXEmpty {
519		// x is negative and y is positive, so x >> y is non-positive.
520		if negX[0] == nil {
521			ret.lowerMin(biggerInt{extra: -1})
522		} else {
523			ret.lowerMin(biggerInt{i: bigIntRsh(negX[0], y[0])})
524		}
525		if y[1] == nil {
526			ret.raiseMax(biggerInt{i: big.NewInt(-1)})
527		} else {
528			ret.raiseMax(biggerInt{i: bigIntRsh(negX[1], y[1])})
529		}
530	}
531
532	if !posXEmpty {
533		// x is positive and y is positive, so x >> y is non-negative.
534		if y[1] == nil {
535			ret.lowerMin(biggerInt{i: big.NewInt(0)})
536		} else {
537			ret.lowerMin(biggerInt{i: bigIntRsh(posX[0], y[1])})
538		}
539		if posX[1] == nil {
540			ret.raiseMax(biggerInt{extra: +1})
541		} else {
542			ret.raiseMax(biggerInt{i: bigIntRsh(posX[1], y[0])})
543		}
544	}
545
546	return ret.toIntRange(), true
547}
548
549// And returns z = x & y.
550//
551// ok is false (and z will be IntRange{nil, nil}) if x or y contains at least
552// one negative value. Otherwise, ok is true.
553//
554// TODO: implement bit-wise operations (with tight bounds) on negative
555// integers. In that case, we could drop the "ok" return value.
556func (x IntRange) And(y IntRange) (z IntRange, ok bool) {
557	if x.Empty() || y.Empty() {
558		return empty(), true
559	}
560	if x.ContainsNegative() || y.ContainsNegative() {
561		return IntRange{}, false
562	}
563
564	zMax := (*big.Int)(nil)
565	if x[1] != nil {
566		if y[1] != nil {
567			zMax = x.andMax(y)
568		} else {
569			return IntRange{big.NewInt(0), x[1]}, true
570		}
571	} else {
572		if y[1] != nil {
573			return IntRange{big.NewInt(0), y[1]}, true
574		} else {
575			return IntRange{big.NewInt(0), nil}, true
576		}
577	}
578
579	// andMin(x, y) is ~orMax(~x, ~y).
580	notX := IntRange{
581		big.NewInt(0).Not(x[1]),
582		big.NewInt(0).Not(x[0]),
583	}
584	notY := IntRange{
585		big.NewInt(0).Not(y[1]),
586		big.NewInt(0).Not(y[0]),
587	}
588	zMin := notX.orMax(notY)
589	zMin.Not(zMin)
590
591	return IntRange{zMin, zMax}, true
592}
593
594// Or returns z = x | y.
595//
596// ok is false (and z will be IntRange{nil, nil}) if x or y contains at least
597// one negative value. Otherwise, ok is true.
598//
599// TODO: implement bit-wise operations (with tight bounds) on negative
600// integers. In that case, we could drop the "ok" return value.
601func (x IntRange) Or(y IntRange) (z IntRange, ok bool) {
602	if x.Empty() || y.Empty() {
603		return empty(), true
604	}
605	if x.ContainsNegative() || y.ContainsNegative() {
606		return IntRange{}, false
607	}
608
609	zMax := (*big.Int)(nil)
610	if x[1] != nil && y[1] != nil {
611		zMax = x.orMax(y)
612	} else {
613		// Keep zMax as nil, which means that (x | y) can be arbitrarily large.
614		//
615		// If the integers xx and yy are in the intervals x and y, then (xx |
616		// yy) is at least yy, since a bit-wise or can only turn bits on, and
617		// yy is at least y's lower bound, y[0].
618		//
619		// Therefore, (z[0] >= x[0]) && (z[0] >= y[0]) is a necessary bound.
620		// The smaller of those is also a sufficient bound if that smaller
621		// value is contained in the other interval. For example, if both xx
622		// and yy can be x[0], then (x[0] | x[0]) is simply x[0].
623		if x.ContainsInt(y[0]) {
624			return IntRange{y[0], nil}, true
625		}
626		if y.ContainsInt(x[0]) {
627			return IntRange{x[0], nil}, true
628		}
629		if x[1] == nil && y[1] == nil {
630			panic("unreachable")
631		}
632
633		// The two intervals are non-empty but don't overlap. Furthermore,
634		// exactly one of the two intervals have an infinite upper bound.
635		// Without loss of generality, assume that that interval is y.
636		//
637		// Therefore, (x[0] <= x[1]) && (x[1] < y[0]) && (y[1] == nil).
638		if x[1] == nil {
639			x, y = y, x
640		}
641		if x[1].Cmp(y[0]) >= 0 {
642			panic("unreachable")
643		}
644
645		// We've already calculated zMax: it is infinite. To calculate zMin,
646		// also known as z[0], replace the infinite upper bound y[1] with a
647		// finite value equal to right-filling all of y[0]'s bits.
648		y[1] = big.NewInt(0).Set(y[0])
649		bitFillRight(y[1])
650	}
651
652	// orMin(x, y) is ~andMax(~x, ~y).
653	notX := IntRange{
654		big.NewInt(0).Not(x[1]),
655		big.NewInt(0).Not(x[0]),
656	}
657	notY := IntRange{
658		big.NewInt(0).Not(y[1]),
659		big.NewInt(0).Not(y[0]),
660	}
661	zMin := notX.andMax(notY)
662	zMin.Not(zMin)
663
664	return IntRange{zMin, zMax}, true
665}
666
667// The andMax and orMax algorithms are tricky.
668//
669// First, some notation. Let x and y be intervals, and in math notation, denote
670// those intervals' bounds as [xMin, xMax] and [yMin, yMax]. In Go terms, x is
671// an IntRange, xMin is x[0], xMax is x[1], and likewise for y. In the
672// algorithm discussion below, we'll use square brackets only for denoting
673// intervals, not array indices, and so we'll say xMin instead of x[0].
674//
675// xMin, xMax, yMin and yMax are all assumed to be finite (i.e. a non-nil
676// *big.Int) and non-negative. The caller is responsible for enforcing this.
677//
678// For a given range r, define maximal(r) to be the integers in r for which you
679// cannot flip any bits from 0 to 1 and have the result still be in r. Clearly
680// rMax is in maximal(r), but there are other elements as well -- for each bit
681// that is set in rMax, if you unset that bit, and set all bits to its right,
682// the result is also in maximal(r) as long as it is >= rMin (which is true iff
683// the bit is in bitFillRight(rMax & ~rMin).
684//
685// Clearly x.andMax(y) == maximal(x).andMax(maximal(y)) and x.orMax(y) ==
686// maximal(x).orMax(maximal(y)) -- that is, we only need to consider the
687// maximal elements in each range.
688//
689// For orMax, the max is achieved by starting with xMax | yMax, and then
690// realizing that we can get a larger result by choosing the leftmost bit in
691// xMax & yMax (which we effectively have twice), flipping it to zero in either
692// of the inputs, and replacing all bits to its right with 1s. However, that
693// might end up with the input being below the minimum in its range, so instead
694// of considering all bits in xMax & yMax, we have to restrict to those that
695// are also set in either bitFillRight(xMax & ~xMin) or bitFillRight(yMax &
696// ~yMin).
697//
698// For andMax, we can again only consider the maximal elements. Here, we have
699// either yMax and the best maximal element from x, or xMax and the best
700// maximal element from y. For symmetry assume it's the former (though we must
701// actually check both).
702//
703// We take yMax, and then the maximal element from x that is chosen by flipping
704// the leftmost bit in xMax that will result in a number that is >= xMin and is
705// not also set in yMax. That is, the leftmost bit in bitFillRight(xMax &
706// ~xMin) & xMax & ~yMax.
707
708// andMax returns an exact solution for the maximum possible (xx & yy), for all
709// possible xx in x and yy in y.
710//
711// Algorithm:
712//  // If the two intervals overlap, the result is the minimum of the two
713//  // intervals' maxima.
714//  //
715//  // This overlaps code path is just an optimization.
716//  if overlaps(x, y) {
717//    return min(xMax, yMax)
718//  }
719//  xFlip   = bitFillRight(bitFillRight(xMax & ~xMin) & xMax & ~yMax)
720//  xResult = yMax & ((xMax & ~xFlip) | (xFlip >> 1))
721//  yFlip   = bitFillRight(bitFillRight(yMax & ~yMin) & yMax & ~xMax)
722//  yResult = xMax & ((yMax & ~yFlip) | (yFlip >> 1))
723//  return max(xResult, yResult)
724//
725// If xMin and yMin are both zero, the overlaps branch is taken.
726//
727// TODO: can this algorithm be simplified??
728func (x IntRange) andMax(y IntRange) *big.Int {
729	// Check for overlap.
730	if (y[1].Cmp(x[0]) >= 0) && (x[1].Cmp(y[0]) >= 0) {
731		min := x[1]
732		if x[1].Cmp(y[1]) > 0 {
733			min = y[1]
734		}
735		return min
736	}
737
738	// Otherwise, x and y don't overlap. Four examples:
739	//  - Example #0: x is [1, 3] and y is [ 4,  9], andMax is 3.
740	//  - Example #1: x is [3, 4] and y is [ 5,  6], andMax is 4.
741	//  - Example #2: x is [4, 5] and y is [ 6,  7], andMax is 5.
742	//  - Example #3: x is [7, 7] and y is [12, 14], andMax is 6.
743
744	i := big.NewInt(0)
745	j := big.NewInt(0)
746	k := big.NewInt(0)
747
748	// Calculate xFlip and xResult.
749	{
750		// j = bitFillRight(xMax & ~xMin)
751		//
752		// For example #0, j = bfr(3 & ~1) = bfr(2) = 3.
753		// For example #1, j = bfr(4 & ~3) = bfr(4) = 7.
754		// For example #2, j = bfr(5 & ~4) = bfr(1) = 1.
755		// For example #3, j = bfr(7 & ~7) = bfr(0) = 0.
756		j.AndNot(x[1], x[0])
757		bitFillRight(j)
758
759		// j = xFlip = bitFillRight(j & xMax & ~yMax)
760		//
761		// For example #0, j = bfr(3 & 3 & ~ 9) = bfr(2) = 3.
762		// For example #1, j = bfr(7 & 4 & ~ 6) = bfr(0) = 0.
763		// For example #2, j = bfr(1 & 5 & ~ 7) = bfr(0) = 0.
764		// For example #3, j = bfr(0 & 7 & ~15) = bfr(0) = 0.
765		j.And(j, x[1])
766		j.AndNot(j, y[1])
767		bitFillRight(j)
768
769		// i = xMax & ~xFlip
770		//
771		// For example #0, i = 3 & ~3 = 0.
772		// For example #1, i = 4 & ~0 = 4.
773		// For example #2, i = 5 & ~0 = 5.
774		// For example #3, i = 7 & ~0 = 7.
775		i.AndNot(x[1], j)
776
777		// j = xResult = yMax & (i | (xFlip >> 1))
778		//
779		// For example #0, j =  9 & (0 | (3 >> 1)) = 1.
780		// For example #1, j =  6 & (4 | (0 >> 1)) = 4.
781		// For example #2, j =  7 & (5 | (0 >> 1)) = 5.
782		// For example #3, j = 14 & (7 | (0 >> 1)) = 6.
783		j.Rsh(j, 1)
784		j.Or(j, i)
785		j.And(j, y[1])
786	}
787
788	// Calculate yFlip and yResult.
789	{
790		// k = bitFillRight(yMax & ~yMin)
791		//
792		// For example #0, k = bfr( 9 & ~ 4) = bfr(9) = 15.
793		// For example #1, k = bfr( 6 & ~ 5) = bfr(2) =  3.
794		// For example #2, k = bfr( 7 & ~ 6) = bfr(1) =  1.
795		// For example #3, k = bfr(14 & ~12) = bfr(2) =  3.
796		k.AndNot(y[1], y[0])
797		bitFillRight(k)
798
799		// k = yFlip = bitFillRight(k & yMax & ~xMax)
800		//
801		// For example #0, k = bfr(15 &  9 & ~3) = bfr(8) = 15.
802		// For example #1, k = bfr( 3 &  6 & ~4) = bfr(2) =  3.
803		// For example #2, k = bfr( 1 & 14 & ~5) = bfr(0) =  0.
804		// For example #3, k = bfr( 3 &  7 & ~7) = bfr(0) =  0.
805		k.And(k, y[1])
806		k.AndNot(k, x[1])
807		bitFillRight(k)
808
809		// i = yMax & ~yFlip
810		//
811		// For example #0, i =  9 & ~15 =  0.
812		// For example #1, i =  6 & ~ 3 =  4.
813		// For example #2, i =  7 & ~ 0 =  7.
814		// For example #3, i = 14 & ~ 0 = 14.
815		i.AndNot(y[1], k)
816
817		// k = yResult = xMax & (i | (yFlip >> 1))
818		//
819		// For example #0, k = 3 & ( 0 | (15 >> 1)) = 3.
820		// For example #1, k = 4 & ( 4 | ( 3 >> 1)) = 4.
821		// For example #2, k = 5 & ( 7 | ( 0 >> 1)) = 5.
822		// For example #3, k = 7 & (14 | ( 0 >> 1)) = 6.
823		k.Rsh(k, 1)
824		k.Or(k, i)
825		k.And(k, x[1])
826	}
827
828	// return max(xResult, yResult)
829	//
830	// For example #0, return max(1, 3).
831	// For example #1, return max(4, 4).
832	// For example #2, return max(5, 5).
833	// For example #3, return max(6, 6).
834	if j.Cmp(k) < 0 {
835		return k
836	}
837	return j
838}
839
840// orMax returns an exact solution for the maximum possible (xx | yy), for all
841// possible xx in x and yy in y.
842//
843// Algorithm:
844//  droppable = bitFillRight((xMax & ~xMin) | (yMax & ~yMin))
845//  available = xMax & yMax & droppable
846//  return xMax | yMax | (bitFillRight(available) >> 1)
847//
848// If xMin and yMin are both zero, this simplifies to:
849//  available = xMax & yMax
850//  return xMax | yMax | (bitFillRight(available) >> 1)
851func (x IntRange) orMax(y IntRange) *big.Int {
852	if x[0].Sign() == 0 && y[0].Sign() == 0 {
853		i := big.NewInt(0)
854		i.And(x[1], y[1])
855		bitFillRight(i)
856		i.Rsh(i, 1)
857		i.Or(i, x[1])
858		i.Or(i, y[1])
859		return i
860	}
861
862	// Four examples:
863	//  - Example #0: x is [1, 3] and y is [ 4,  9], orMax is 11.
864	//  - Example #1: x is [3, 4] and y is [ 5,  6], orMax is  7.
865	//  - Example #2: x is [4, 5] and y is [ 6,  7], orMax is  7.
866	//  - Example #3: x is [7, 7] and y is [12, 14], orMax is 15.
867
868	i := big.NewInt(0)
869	j := big.NewInt(0)
870
871	// j = droppable = bitFillRight((xMax & ~xMin) | (yMax & ~yMin))
872	//
873	// For example #0, j = bfr((3 & ~1) | ( 9 & ~ 4)) = bfr(2 | 9) = 15.
874	// For example #1, j = bfr((4 & ~3) | ( 6 & ~ 5)) = bfr(4 | 2) =  7.
875	// For example #2, j = bfr((5 & ~4) | ( 7 & ~ 6)) = bfr(1 | 1) =  1.
876	// For example #3, j = bfr((7 & ~7) | (14 & ~12)) = bfr(0 | 2) =  3.
877	i.AndNot(x[1], x[0])
878	j.AndNot(y[1], y[0])
879	j.Or(j, i)
880	bitFillRight(j)
881
882	// j = available = xMax & yMax & j
883	//
884	// For example #0, j = 3 &  9 & 15 = 1.
885	// For example #1, j = 4 &  6 &  7 = 4.
886	// For example #2, j = 5 &  7 &  1 = 1.
887	// For example #3, j = 7 & 14 &  3 = 2.
888	j.And(j, x[1])
889	j.And(j, y[1])
890
891	// j = bitFillRight(j) >> 1
892	//
893	// For example #0, j = bfr(1) >> 1 = 0.
894	// For example #1, j = bfr(4) >> 1 = 3.
895	// For example #2, j = bfr(1) >> 1 = 0.
896	// For example #3, j = bfr(2) >> 1 = 1.
897	bitFillRight(j)
898	j.Rsh(j, 1)
899
900	// return xMax | yMax | j
901	//
902	// For example #0, return 3 |  9 | 0 = 11.
903	// For example #1, return 4 |  6 | 3 =  7.
904	// For example #2, return 5 |  7 | 0 =  7.
905	// For example #3, return 7 | 14 | 1 = 15.
906	j.Or(j, x[1])
907	j.Or(j, y[1])
908	return j
909}
910
911// bitFillRight modifies i to round up to the next power of 2 minus 1:
912//  - If i is +0 then bitFillRight(i) sets i to  0.
913//  - If i is +1 then bitFillRight(i) sets i to  1.
914//  - If i is +2 then bitFillRight(i) sets i to  3.
915//  - If i is +3 then bitFillRight(i) sets i to  3.
916//  - If i is +4 then bitFillRight(i) sets i to  7.
917//  - If i is +5 then bitFillRight(i) sets i to  7.
918//  - If i is +6 then bitFillRight(i) sets i to  7.
919//  - If i is +7 then bitFillRight(i) sets i to  7.
920//  - If i is +8 then bitFillRight(i) sets i to 15.
921//  - If i is +9 then bitFillRight(i) sets i to 15.
922//  - Etc.
923func bitFillRight(i *big.Int) {
924	if s := i.Sign(); s < 0 {
925		panic("TODO: implement bit-wise operations on negative integers")
926	} else if s == 0 {
927		return
928	}
929	n := i.BitLen()
930	if n > 0xFFFF {
931		panic("interval: input is too large")
932	}
933	i.SetInt64(1)
934	i.Lsh(i, uint(n))
935	i.Sub(i, one)
936}
937