Index: quadratic-test.cpp =================================================================== --- /dev/null +++ quadratic-test.cpp @@ -0,0 +1,76 @@ +#include +#include +#include +#include +#include +#include +#include + +using namespace llvm; + +int64_t OverflowBits(int64_t V, unsigned W) { + return V & -(1 << W); +} + +void Validate(int A, int B, int C, unsigned Width, int Solution) { + int Mask = (1 << Width) - 1; + + if (Solution == 0) { + assert((C & Mask) == 0 && "Invalid zero solution"); + return; + } + assert(Solution >= 0 && "Solution should be non-negative"); + + auto Error = [&] (StringRef Msg, int64_t X, int64_t OverEntry, + int64_t OverX) { + std::cerr << Msg.str() << A << "x^2 + " << B << "x + " << C + << ", solution " << Solution << "\nOverflow bits on entry: " + << OverEntry << ", overflow bits at iteration " << X << ": " + << OverX << '\n'; + abort(); + }; + + int64_t Over0 = OverflowBits(C, Width); + + // This is the important part: make sure that there is no solution that + // is less than the calculated one. + for (int X = 1; X < Solution-1; ++X) { + int64_t VX = A*X*X + B*X + C; + int64_t OverX = OverflowBits(VX, Width); + if ((VX & Mask) == 0 || OverX != Over0) + Error("Unexpected early overflow: ", X, Over0, OverX); + } + + // Verify that the calculated solution is indeed a solution. + int64_t VS = A*Solution*Solution + B*Solution + C; + int64_t OverS = OverflowBits(VS, Width); + if ((VS & Mask) != 0 && OverS == Over0) + Error("Expected overflow: ", Solution, Over0, OverS); +} + +void Iterate(unsigned Width) { + assert(1 < Width && Width < 32); + int Low = -(1 << (Width-1)); + int High = (1 << (Width-1)); + + for (int A = Low; A != High; ++A) { + if (A == 0) + continue; + for (int B = Low; B != High; ++B) { + for (int C = Low; C != High; ++C) { + Optional S = APIntOps::SolveQuadraticEquationWrap( + APInt(Width, A), APInt(Width, B), APInt(Width, C), + Width); + if (S.hasValue()) + Validate(A, B, C, Width, S->getSExtValue()); + } + } + } +} + +int main() { + for (unsigned i = 2; i != 11; ++i) { + std::cout << "Checking width " << i << '\n'; + Iterate(i); + } +} Index: quadratic-test.mak =================================================================== --- /dev/null +++ quadratic-test.mak @@ -0,0 +1,10 @@ +CPPFLAGS = $(shell llvm-config --cppflags) +SYSLIBS = $(shell llvm-config --system-libs) +LDFLAGS = $(shell llvm-config --ldflags) +CC = clang++ + +quadratic-test: quadratic-test.o + $(CC) $< -lLLVMSupport $(LDFLAGS) $(SYSLIBS) -lc++ -o $@ + +%.o : %.cpp + $(CC) -O2 $(CPPFLAGS) -c $<