xref: /llvm-project/llvm/lib/Support/SlowDynamicAPInt.cpp (revision 1a0e67d73023e7ad9e7e79f66afb43a6f2561d04)
1*1a0e67d7SRamkumar Ramachandra //===- SlowDynamicAPInt.cpp - SlowDynamicAPInt Implementation -------------===//
2*1a0e67d7SRamkumar Ramachandra //
3*1a0e67d7SRamkumar Ramachandra // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*1a0e67d7SRamkumar Ramachandra // See https://llvm.org/LICENSE.txt for license information.
5*1a0e67d7SRamkumar Ramachandra // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*1a0e67d7SRamkumar Ramachandra //
7*1a0e67d7SRamkumar Ramachandra //===----------------------------------------------------------------------===//
8*1a0e67d7SRamkumar Ramachandra 
9*1a0e67d7SRamkumar Ramachandra #include "llvm/ADT/SlowDynamicAPInt.h"
10*1a0e67d7SRamkumar Ramachandra #include "llvm/ADT/Hashing.h"
11*1a0e67d7SRamkumar Ramachandra #include "llvm/Support/Debug.h"
12*1a0e67d7SRamkumar Ramachandra #include "llvm/Support/raw_ostream.h"
13*1a0e67d7SRamkumar Ramachandra 
14*1a0e67d7SRamkumar Ramachandra using namespace llvm;
15*1a0e67d7SRamkumar Ramachandra using namespace detail;
16*1a0e67d7SRamkumar Ramachandra 
SlowDynamicAPInt(int64_t Val)17*1a0e67d7SRamkumar Ramachandra SlowDynamicAPInt::SlowDynamicAPInt(int64_t Val)
18*1a0e67d7SRamkumar Ramachandra     : Val(64, Val, /*isSigned=*/true) {}
SlowDynamicAPInt()19*1a0e67d7SRamkumar Ramachandra SlowDynamicAPInt::SlowDynamicAPInt() : SlowDynamicAPInt(0) {}
SlowDynamicAPInt(const APInt & Val)20*1a0e67d7SRamkumar Ramachandra SlowDynamicAPInt::SlowDynamicAPInt(const APInt &Val) : Val(Val) {}
operator =(int64_t Val)21*1a0e67d7SRamkumar Ramachandra SlowDynamicAPInt &SlowDynamicAPInt::operator=(int64_t Val) {
22*1a0e67d7SRamkumar Ramachandra   return *this = SlowDynamicAPInt(Val);
23*1a0e67d7SRamkumar Ramachandra }
operator int64_t() const24*1a0e67d7SRamkumar Ramachandra SlowDynamicAPInt::operator int64_t() const { return Val.getSExtValue(); }
25*1a0e67d7SRamkumar Ramachandra 
hash_value(const SlowDynamicAPInt & X)26*1a0e67d7SRamkumar Ramachandra hash_code detail::hash_value(const SlowDynamicAPInt &X) {
27*1a0e67d7SRamkumar Ramachandra   return hash_value(X.Val);
28*1a0e67d7SRamkumar Ramachandra }
29*1a0e67d7SRamkumar Ramachandra 
30*1a0e67d7SRamkumar Ramachandra /// ---------------------------------------------------------------------------
31*1a0e67d7SRamkumar Ramachandra /// Convenience operator overloads for int64_t.
32*1a0e67d7SRamkumar Ramachandra /// ---------------------------------------------------------------------------
operator +=(SlowDynamicAPInt & A,int64_t B)33*1a0e67d7SRamkumar Ramachandra SlowDynamicAPInt &detail::operator+=(SlowDynamicAPInt &A, int64_t B) {
34*1a0e67d7SRamkumar Ramachandra   return A += SlowDynamicAPInt(B);
35*1a0e67d7SRamkumar Ramachandra }
operator -=(SlowDynamicAPInt & A,int64_t B)36*1a0e67d7SRamkumar Ramachandra SlowDynamicAPInt &detail::operator-=(SlowDynamicAPInt &A, int64_t B) {
37*1a0e67d7SRamkumar Ramachandra   return A -= SlowDynamicAPInt(B);
38*1a0e67d7SRamkumar Ramachandra }
operator *=(SlowDynamicAPInt & A,int64_t B)39*1a0e67d7SRamkumar Ramachandra SlowDynamicAPInt &detail::operator*=(SlowDynamicAPInt &A, int64_t B) {
40*1a0e67d7SRamkumar Ramachandra   return A *= SlowDynamicAPInt(B);
41*1a0e67d7SRamkumar Ramachandra }
operator /=(SlowDynamicAPInt & A,int64_t B)42*1a0e67d7SRamkumar Ramachandra SlowDynamicAPInt &detail::operator/=(SlowDynamicAPInt &A, int64_t B) {
43*1a0e67d7SRamkumar Ramachandra   return A /= SlowDynamicAPInt(B);
44*1a0e67d7SRamkumar Ramachandra }
operator %=(SlowDynamicAPInt & A,int64_t B)45*1a0e67d7SRamkumar Ramachandra SlowDynamicAPInt &detail::operator%=(SlowDynamicAPInt &A, int64_t B) {
46*1a0e67d7SRamkumar Ramachandra   return A %= SlowDynamicAPInt(B);
47*1a0e67d7SRamkumar Ramachandra }
48*1a0e67d7SRamkumar Ramachandra 
operator ==(const SlowDynamicAPInt & A,int64_t B)49*1a0e67d7SRamkumar Ramachandra bool detail::operator==(const SlowDynamicAPInt &A, int64_t B) {
50*1a0e67d7SRamkumar Ramachandra   return A == SlowDynamicAPInt(B);
51*1a0e67d7SRamkumar Ramachandra }
operator !=(const SlowDynamicAPInt & A,int64_t B)52*1a0e67d7SRamkumar Ramachandra bool detail::operator!=(const SlowDynamicAPInt &A, int64_t B) {
53*1a0e67d7SRamkumar Ramachandra   return A != SlowDynamicAPInt(B);
54*1a0e67d7SRamkumar Ramachandra }
operator >(const SlowDynamicAPInt & A,int64_t B)55*1a0e67d7SRamkumar Ramachandra bool detail::operator>(const SlowDynamicAPInt &A, int64_t B) {
56*1a0e67d7SRamkumar Ramachandra   return A > SlowDynamicAPInt(B);
57*1a0e67d7SRamkumar Ramachandra }
operator <(const SlowDynamicAPInt & A,int64_t B)58*1a0e67d7SRamkumar Ramachandra bool detail::operator<(const SlowDynamicAPInt &A, int64_t B) {
59*1a0e67d7SRamkumar Ramachandra   return A < SlowDynamicAPInt(B);
60*1a0e67d7SRamkumar Ramachandra }
operator <=(const SlowDynamicAPInt & A,int64_t B)61*1a0e67d7SRamkumar Ramachandra bool detail::operator<=(const SlowDynamicAPInt &A, int64_t B) {
62*1a0e67d7SRamkumar Ramachandra   return A <= SlowDynamicAPInt(B);
63*1a0e67d7SRamkumar Ramachandra }
operator >=(const SlowDynamicAPInt & A,int64_t B)64*1a0e67d7SRamkumar Ramachandra bool detail::operator>=(const SlowDynamicAPInt &A, int64_t B) {
65*1a0e67d7SRamkumar Ramachandra   return A >= SlowDynamicAPInt(B);
66*1a0e67d7SRamkumar Ramachandra }
operator +(const SlowDynamicAPInt & A,int64_t B)67*1a0e67d7SRamkumar Ramachandra SlowDynamicAPInt detail::operator+(const SlowDynamicAPInt &A, int64_t B) {
68*1a0e67d7SRamkumar Ramachandra   return A + SlowDynamicAPInt(B);
69*1a0e67d7SRamkumar Ramachandra }
operator -(const SlowDynamicAPInt & A,int64_t B)70*1a0e67d7SRamkumar Ramachandra SlowDynamicAPInt detail::operator-(const SlowDynamicAPInt &A, int64_t B) {
71*1a0e67d7SRamkumar Ramachandra   return A - SlowDynamicAPInt(B);
72*1a0e67d7SRamkumar Ramachandra }
operator *(const SlowDynamicAPInt & A,int64_t B)73*1a0e67d7SRamkumar Ramachandra SlowDynamicAPInt detail::operator*(const SlowDynamicAPInt &A, int64_t B) {
74*1a0e67d7SRamkumar Ramachandra   return A * SlowDynamicAPInt(B);
75*1a0e67d7SRamkumar Ramachandra }
operator /(const SlowDynamicAPInt & A,int64_t B)76*1a0e67d7SRamkumar Ramachandra SlowDynamicAPInt detail::operator/(const SlowDynamicAPInt &A, int64_t B) {
77*1a0e67d7SRamkumar Ramachandra   return A / SlowDynamicAPInt(B);
78*1a0e67d7SRamkumar Ramachandra }
operator %(const SlowDynamicAPInt & A,int64_t B)79*1a0e67d7SRamkumar Ramachandra SlowDynamicAPInt detail::operator%(const SlowDynamicAPInt &A, int64_t B) {
80*1a0e67d7SRamkumar Ramachandra   return A % SlowDynamicAPInt(B);
81*1a0e67d7SRamkumar Ramachandra }
82*1a0e67d7SRamkumar Ramachandra 
operator ==(int64_t A,const SlowDynamicAPInt & B)83*1a0e67d7SRamkumar Ramachandra bool detail::operator==(int64_t A, const SlowDynamicAPInt &B) {
84*1a0e67d7SRamkumar Ramachandra   return SlowDynamicAPInt(A) == B;
85*1a0e67d7SRamkumar Ramachandra }
operator !=(int64_t A,const SlowDynamicAPInt & B)86*1a0e67d7SRamkumar Ramachandra bool detail::operator!=(int64_t A, const SlowDynamicAPInt &B) {
87*1a0e67d7SRamkumar Ramachandra   return SlowDynamicAPInt(A) != B;
88*1a0e67d7SRamkumar Ramachandra }
operator >(int64_t A,const SlowDynamicAPInt & B)89*1a0e67d7SRamkumar Ramachandra bool detail::operator>(int64_t A, const SlowDynamicAPInt &B) {
90*1a0e67d7SRamkumar Ramachandra   return SlowDynamicAPInt(A) > B;
91*1a0e67d7SRamkumar Ramachandra }
operator <(int64_t A,const SlowDynamicAPInt & B)92*1a0e67d7SRamkumar Ramachandra bool detail::operator<(int64_t A, const SlowDynamicAPInt &B) {
93*1a0e67d7SRamkumar Ramachandra   return SlowDynamicAPInt(A) < B;
94*1a0e67d7SRamkumar Ramachandra }
operator <=(int64_t A,const SlowDynamicAPInt & B)95*1a0e67d7SRamkumar Ramachandra bool detail::operator<=(int64_t A, const SlowDynamicAPInt &B) {
96*1a0e67d7SRamkumar Ramachandra   return SlowDynamicAPInt(A) <= B;
97*1a0e67d7SRamkumar Ramachandra }
operator >=(int64_t A,const SlowDynamicAPInt & B)98*1a0e67d7SRamkumar Ramachandra bool detail::operator>=(int64_t A, const SlowDynamicAPInt &B) {
99*1a0e67d7SRamkumar Ramachandra   return SlowDynamicAPInt(A) >= B;
100*1a0e67d7SRamkumar Ramachandra }
operator +(int64_t A,const SlowDynamicAPInt & B)101*1a0e67d7SRamkumar Ramachandra SlowDynamicAPInt detail::operator+(int64_t A, const SlowDynamicAPInt &B) {
102*1a0e67d7SRamkumar Ramachandra   return SlowDynamicAPInt(A) + B;
103*1a0e67d7SRamkumar Ramachandra }
operator -(int64_t A,const SlowDynamicAPInt & B)104*1a0e67d7SRamkumar Ramachandra SlowDynamicAPInt detail::operator-(int64_t A, const SlowDynamicAPInt &B) {
105*1a0e67d7SRamkumar Ramachandra   return SlowDynamicAPInt(A) - B;
106*1a0e67d7SRamkumar Ramachandra }
operator *(int64_t A,const SlowDynamicAPInt & B)107*1a0e67d7SRamkumar Ramachandra SlowDynamicAPInt detail::operator*(int64_t A, const SlowDynamicAPInt &B) {
108*1a0e67d7SRamkumar Ramachandra   return SlowDynamicAPInt(A) * B;
109*1a0e67d7SRamkumar Ramachandra }
operator /(int64_t A,const SlowDynamicAPInt & B)110*1a0e67d7SRamkumar Ramachandra SlowDynamicAPInt detail::operator/(int64_t A, const SlowDynamicAPInt &B) {
111*1a0e67d7SRamkumar Ramachandra   return SlowDynamicAPInt(A) / B;
112*1a0e67d7SRamkumar Ramachandra }
operator %(int64_t A,const SlowDynamicAPInt & B)113*1a0e67d7SRamkumar Ramachandra SlowDynamicAPInt detail::operator%(int64_t A, const SlowDynamicAPInt &B) {
114*1a0e67d7SRamkumar Ramachandra   return SlowDynamicAPInt(A) % B;
115*1a0e67d7SRamkumar Ramachandra }
116*1a0e67d7SRamkumar Ramachandra 
getMaxWidth(const APInt & A,const APInt & B)117*1a0e67d7SRamkumar Ramachandra static unsigned getMaxWidth(const APInt &A, const APInt &B) {
118*1a0e67d7SRamkumar Ramachandra   return std::max(A.getBitWidth(), B.getBitWidth());
119*1a0e67d7SRamkumar Ramachandra }
120*1a0e67d7SRamkumar Ramachandra 
121*1a0e67d7SRamkumar Ramachandra /// ---------------------------------------------------------------------------
122*1a0e67d7SRamkumar Ramachandra /// Comparison operators.
123*1a0e67d7SRamkumar Ramachandra /// ---------------------------------------------------------------------------
124*1a0e67d7SRamkumar Ramachandra 
125*1a0e67d7SRamkumar Ramachandra // TODO: consider instead making APInt::compare available and using that.
operator ==(const SlowDynamicAPInt & O) const126*1a0e67d7SRamkumar Ramachandra bool SlowDynamicAPInt::operator==(const SlowDynamicAPInt &O) const {
127*1a0e67d7SRamkumar Ramachandra   unsigned Width = getMaxWidth(Val, O.Val);
128*1a0e67d7SRamkumar Ramachandra   return Val.sext(Width) == O.Val.sext(Width);
129*1a0e67d7SRamkumar Ramachandra }
operator !=(const SlowDynamicAPInt & O) const130*1a0e67d7SRamkumar Ramachandra bool SlowDynamicAPInt::operator!=(const SlowDynamicAPInt &O) const {
131*1a0e67d7SRamkumar Ramachandra   unsigned Width = getMaxWidth(Val, O.Val);
132*1a0e67d7SRamkumar Ramachandra   return Val.sext(Width) != O.Val.sext(Width);
133*1a0e67d7SRamkumar Ramachandra }
operator >(const SlowDynamicAPInt & O) const134*1a0e67d7SRamkumar Ramachandra bool SlowDynamicAPInt::operator>(const SlowDynamicAPInt &O) const {
135*1a0e67d7SRamkumar Ramachandra   unsigned Width = getMaxWidth(Val, O.Val);
136*1a0e67d7SRamkumar Ramachandra   return Val.sext(Width).sgt(O.Val.sext(Width));
137*1a0e67d7SRamkumar Ramachandra }
operator <(const SlowDynamicAPInt & O) const138*1a0e67d7SRamkumar Ramachandra bool SlowDynamicAPInt::operator<(const SlowDynamicAPInt &O) const {
139*1a0e67d7SRamkumar Ramachandra   unsigned Width = getMaxWidth(Val, O.Val);
140*1a0e67d7SRamkumar Ramachandra   return Val.sext(Width).slt(O.Val.sext(Width));
141*1a0e67d7SRamkumar Ramachandra }
operator <=(const SlowDynamicAPInt & O) const142*1a0e67d7SRamkumar Ramachandra bool SlowDynamicAPInt::operator<=(const SlowDynamicAPInt &O) const {
143*1a0e67d7SRamkumar Ramachandra   unsigned Width = getMaxWidth(Val, O.Val);
144*1a0e67d7SRamkumar Ramachandra   return Val.sext(Width).sle(O.Val.sext(Width));
145*1a0e67d7SRamkumar Ramachandra }
operator >=(const SlowDynamicAPInt & O) const146*1a0e67d7SRamkumar Ramachandra bool SlowDynamicAPInt::operator>=(const SlowDynamicAPInt &O) const {
147*1a0e67d7SRamkumar Ramachandra   unsigned Width = getMaxWidth(Val, O.Val);
148*1a0e67d7SRamkumar Ramachandra   return Val.sext(Width).sge(O.Val.sext(Width));
149*1a0e67d7SRamkumar Ramachandra }
150*1a0e67d7SRamkumar Ramachandra 
151*1a0e67d7SRamkumar Ramachandra /// ---------------------------------------------------------------------------
152*1a0e67d7SRamkumar Ramachandra /// Arithmetic operators.
153*1a0e67d7SRamkumar Ramachandra /// ---------------------------------------------------------------------------
154*1a0e67d7SRamkumar Ramachandra 
155*1a0e67d7SRamkumar Ramachandra /// Bring a and b to have the same width and then call op(a, b, overflow).
156*1a0e67d7SRamkumar Ramachandra /// If the overflow bit becomes set, resize a and b to double the width and
157*1a0e67d7SRamkumar Ramachandra /// call op(a, b, overflow), returning its result. The operation with double
158*1a0e67d7SRamkumar Ramachandra /// widths should not also overflow.
runOpWithExpandOnOverflow(const APInt & A,const APInt & B,function_ref<APInt (const APInt &,const APInt &,bool & Overflow)> Op)159*1a0e67d7SRamkumar Ramachandra APInt runOpWithExpandOnOverflow(
160*1a0e67d7SRamkumar Ramachandra     const APInt &A, const APInt &B,
161*1a0e67d7SRamkumar Ramachandra     function_ref<APInt(const APInt &, const APInt &, bool &Overflow)> Op) {
162*1a0e67d7SRamkumar Ramachandra   bool Overflow;
163*1a0e67d7SRamkumar Ramachandra   unsigned Width = getMaxWidth(A, B);
164*1a0e67d7SRamkumar Ramachandra   APInt Ret = Op(A.sext(Width), B.sext(Width), Overflow);
165*1a0e67d7SRamkumar Ramachandra   if (!Overflow)
166*1a0e67d7SRamkumar Ramachandra     return Ret;
167*1a0e67d7SRamkumar Ramachandra 
168*1a0e67d7SRamkumar Ramachandra   Width *= 2;
169*1a0e67d7SRamkumar Ramachandra   Ret = Op(A.sext(Width), B.sext(Width), Overflow);
170*1a0e67d7SRamkumar Ramachandra   assert(!Overflow && "double width should be sufficient to avoid overflow!");
171*1a0e67d7SRamkumar Ramachandra   return Ret;
172*1a0e67d7SRamkumar Ramachandra }
173*1a0e67d7SRamkumar Ramachandra 
operator +(const SlowDynamicAPInt & O) const174*1a0e67d7SRamkumar Ramachandra SlowDynamicAPInt SlowDynamicAPInt::operator+(const SlowDynamicAPInt &O) const {
175*1a0e67d7SRamkumar Ramachandra   return SlowDynamicAPInt(
176*1a0e67d7SRamkumar Ramachandra       runOpWithExpandOnOverflow(Val, O.Val, std::mem_fn(&APInt::sadd_ov)));
177*1a0e67d7SRamkumar Ramachandra }
operator -(const SlowDynamicAPInt & O) const178*1a0e67d7SRamkumar Ramachandra SlowDynamicAPInt SlowDynamicAPInt::operator-(const SlowDynamicAPInt &O) const {
179*1a0e67d7SRamkumar Ramachandra   return SlowDynamicAPInt(
180*1a0e67d7SRamkumar Ramachandra       runOpWithExpandOnOverflow(Val, O.Val, std::mem_fn(&APInt::ssub_ov)));
181*1a0e67d7SRamkumar Ramachandra }
operator *(const SlowDynamicAPInt & O) const182*1a0e67d7SRamkumar Ramachandra SlowDynamicAPInt SlowDynamicAPInt::operator*(const SlowDynamicAPInt &O) const {
183*1a0e67d7SRamkumar Ramachandra   return SlowDynamicAPInt(
184*1a0e67d7SRamkumar Ramachandra       runOpWithExpandOnOverflow(Val, O.Val, std::mem_fn(&APInt::smul_ov)));
185*1a0e67d7SRamkumar Ramachandra }
operator /(const SlowDynamicAPInt & O) const186*1a0e67d7SRamkumar Ramachandra SlowDynamicAPInt SlowDynamicAPInt::operator/(const SlowDynamicAPInt &O) const {
187*1a0e67d7SRamkumar Ramachandra   return SlowDynamicAPInt(
188*1a0e67d7SRamkumar Ramachandra       runOpWithExpandOnOverflow(Val, O.Val, std::mem_fn(&APInt::sdiv_ov)));
189*1a0e67d7SRamkumar Ramachandra }
abs(const SlowDynamicAPInt & X)190*1a0e67d7SRamkumar Ramachandra SlowDynamicAPInt detail::abs(const SlowDynamicAPInt &X) {
191*1a0e67d7SRamkumar Ramachandra   return X >= 0 ? X : -X;
192*1a0e67d7SRamkumar Ramachandra }
ceilDiv(const SlowDynamicAPInt & LHS,const SlowDynamicAPInt & RHS)193*1a0e67d7SRamkumar Ramachandra SlowDynamicAPInt detail::ceilDiv(const SlowDynamicAPInt &LHS,
194*1a0e67d7SRamkumar Ramachandra                                  const SlowDynamicAPInt &RHS) {
195*1a0e67d7SRamkumar Ramachandra   if (RHS == -1)
196*1a0e67d7SRamkumar Ramachandra     return -LHS;
197*1a0e67d7SRamkumar Ramachandra   unsigned Width = getMaxWidth(LHS.Val, RHS.Val);
198*1a0e67d7SRamkumar Ramachandra   return SlowDynamicAPInt(APIntOps::RoundingSDiv(
199*1a0e67d7SRamkumar Ramachandra       LHS.Val.sext(Width), RHS.Val.sext(Width), APInt::Rounding::UP));
200*1a0e67d7SRamkumar Ramachandra }
floorDiv(const SlowDynamicAPInt & LHS,const SlowDynamicAPInt & RHS)201*1a0e67d7SRamkumar Ramachandra SlowDynamicAPInt detail::floorDiv(const SlowDynamicAPInt &LHS,
202*1a0e67d7SRamkumar Ramachandra                                   const SlowDynamicAPInt &RHS) {
203*1a0e67d7SRamkumar Ramachandra   if (RHS == -1)
204*1a0e67d7SRamkumar Ramachandra     return -LHS;
205*1a0e67d7SRamkumar Ramachandra   unsigned Width = getMaxWidth(LHS.Val, RHS.Val);
206*1a0e67d7SRamkumar Ramachandra   return SlowDynamicAPInt(APIntOps::RoundingSDiv(
207*1a0e67d7SRamkumar Ramachandra       LHS.Val.sext(Width), RHS.Val.sext(Width), APInt::Rounding::DOWN));
208*1a0e67d7SRamkumar Ramachandra }
209*1a0e67d7SRamkumar Ramachandra // The RHS is always expected to be positive, and the result
210*1a0e67d7SRamkumar Ramachandra /// is always non-negative.
mod(const SlowDynamicAPInt & LHS,const SlowDynamicAPInt & RHS)211*1a0e67d7SRamkumar Ramachandra SlowDynamicAPInt detail::mod(const SlowDynamicAPInt &LHS,
212*1a0e67d7SRamkumar Ramachandra                              const SlowDynamicAPInt &RHS) {
213*1a0e67d7SRamkumar Ramachandra   assert(RHS >= 1 && "mod is only supported for positive divisors!");
214*1a0e67d7SRamkumar Ramachandra   return LHS % RHS < 0 ? LHS % RHS + RHS : LHS % RHS;
215*1a0e67d7SRamkumar Ramachandra }
216*1a0e67d7SRamkumar Ramachandra 
gcd(const SlowDynamicAPInt & A,const SlowDynamicAPInt & B)217*1a0e67d7SRamkumar Ramachandra SlowDynamicAPInt detail::gcd(const SlowDynamicAPInt &A,
218*1a0e67d7SRamkumar Ramachandra                              const SlowDynamicAPInt &B) {
219*1a0e67d7SRamkumar Ramachandra   assert(A >= 0 && B >= 0 && "operands must be non-negative!");
220*1a0e67d7SRamkumar Ramachandra   unsigned Width = getMaxWidth(A.Val, B.Val);
221*1a0e67d7SRamkumar Ramachandra   return SlowDynamicAPInt(
222*1a0e67d7SRamkumar Ramachandra       APIntOps::GreatestCommonDivisor(A.Val.sext(Width), B.Val.sext(Width)));
223*1a0e67d7SRamkumar Ramachandra }
224*1a0e67d7SRamkumar Ramachandra 
225*1a0e67d7SRamkumar Ramachandra /// Returns the least common multiple of A and B.
lcm(const SlowDynamicAPInt & A,const SlowDynamicAPInt & B)226*1a0e67d7SRamkumar Ramachandra SlowDynamicAPInt detail::lcm(const SlowDynamicAPInt &A,
227*1a0e67d7SRamkumar Ramachandra                              const SlowDynamicAPInt &B) {
228*1a0e67d7SRamkumar Ramachandra   SlowDynamicAPInt X = abs(A);
229*1a0e67d7SRamkumar Ramachandra   SlowDynamicAPInt Y = abs(B);
230*1a0e67d7SRamkumar Ramachandra   return (X * Y) / gcd(X, Y);
231*1a0e67d7SRamkumar Ramachandra }
232*1a0e67d7SRamkumar Ramachandra 
233*1a0e67d7SRamkumar Ramachandra /// This operation cannot overflow.
operator %(const SlowDynamicAPInt & O) const234*1a0e67d7SRamkumar Ramachandra SlowDynamicAPInt SlowDynamicAPInt::operator%(const SlowDynamicAPInt &O) const {
235*1a0e67d7SRamkumar Ramachandra   unsigned Width = std::max(Val.getBitWidth(), O.Val.getBitWidth());
236*1a0e67d7SRamkumar Ramachandra   return SlowDynamicAPInt(Val.sext(Width).srem(O.Val.sext(Width)));
237*1a0e67d7SRamkumar Ramachandra }
238*1a0e67d7SRamkumar Ramachandra 
operator -() const239*1a0e67d7SRamkumar Ramachandra SlowDynamicAPInt SlowDynamicAPInt::operator-() const {
240*1a0e67d7SRamkumar Ramachandra   if (Val.isMinSignedValue()) {
241*1a0e67d7SRamkumar Ramachandra     /// Overflow only occurs when the value is the minimum possible value.
242*1a0e67d7SRamkumar Ramachandra     APInt Ret = Val.sext(2 * Val.getBitWidth());
243*1a0e67d7SRamkumar Ramachandra     return SlowDynamicAPInt(-Ret);
244*1a0e67d7SRamkumar Ramachandra   }
245*1a0e67d7SRamkumar Ramachandra   return SlowDynamicAPInt(-Val);
246*1a0e67d7SRamkumar Ramachandra }
247*1a0e67d7SRamkumar Ramachandra 
248*1a0e67d7SRamkumar Ramachandra /// ---------------------------------------------------------------------------
249*1a0e67d7SRamkumar Ramachandra /// Assignment operators, preincrement, predecrement.
250*1a0e67d7SRamkumar Ramachandra /// ---------------------------------------------------------------------------
operator +=(const SlowDynamicAPInt & O)251*1a0e67d7SRamkumar Ramachandra SlowDynamicAPInt &SlowDynamicAPInt::operator+=(const SlowDynamicAPInt &O) {
252*1a0e67d7SRamkumar Ramachandra   *this = *this + O;
253*1a0e67d7SRamkumar Ramachandra   return *this;
254*1a0e67d7SRamkumar Ramachandra }
operator -=(const SlowDynamicAPInt & O)255*1a0e67d7SRamkumar Ramachandra SlowDynamicAPInt &SlowDynamicAPInt::operator-=(const SlowDynamicAPInt &O) {
256*1a0e67d7SRamkumar Ramachandra   *this = *this - O;
257*1a0e67d7SRamkumar Ramachandra   return *this;
258*1a0e67d7SRamkumar Ramachandra }
operator *=(const SlowDynamicAPInt & O)259*1a0e67d7SRamkumar Ramachandra SlowDynamicAPInt &SlowDynamicAPInt::operator*=(const SlowDynamicAPInt &O) {
260*1a0e67d7SRamkumar Ramachandra   *this = *this * O;
261*1a0e67d7SRamkumar Ramachandra   return *this;
262*1a0e67d7SRamkumar Ramachandra }
operator /=(const SlowDynamicAPInt & O)263*1a0e67d7SRamkumar Ramachandra SlowDynamicAPInt &SlowDynamicAPInt::operator/=(const SlowDynamicAPInt &O) {
264*1a0e67d7SRamkumar Ramachandra   *this = *this / O;
265*1a0e67d7SRamkumar Ramachandra   return *this;
266*1a0e67d7SRamkumar Ramachandra }
operator %=(const SlowDynamicAPInt & O)267*1a0e67d7SRamkumar Ramachandra SlowDynamicAPInt &SlowDynamicAPInt::operator%=(const SlowDynamicAPInt &O) {
268*1a0e67d7SRamkumar Ramachandra   *this = *this % O;
269*1a0e67d7SRamkumar Ramachandra   return *this;
270*1a0e67d7SRamkumar Ramachandra }
operator ++()271*1a0e67d7SRamkumar Ramachandra SlowDynamicAPInt &SlowDynamicAPInt::operator++() {
272*1a0e67d7SRamkumar Ramachandra   *this += 1;
273*1a0e67d7SRamkumar Ramachandra   return *this;
274*1a0e67d7SRamkumar Ramachandra }
275*1a0e67d7SRamkumar Ramachandra 
operator --()276*1a0e67d7SRamkumar Ramachandra SlowDynamicAPInt &SlowDynamicAPInt::operator--() {
277*1a0e67d7SRamkumar Ramachandra   *this -= 1;
278*1a0e67d7SRamkumar Ramachandra   return *this;
279*1a0e67d7SRamkumar Ramachandra }
280*1a0e67d7SRamkumar Ramachandra 
281*1a0e67d7SRamkumar Ramachandra /// ---------------------------------------------------------------------------
282*1a0e67d7SRamkumar Ramachandra /// Printing.
283*1a0e67d7SRamkumar Ramachandra /// ---------------------------------------------------------------------------
print(raw_ostream & OS) const284*1a0e67d7SRamkumar Ramachandra void SlowDynamicAPInt::print(raw_ostream &OS) const { OS << Val; }
285*1a0e67d7SRamkumar Ramachandra 
dump() const286*1a0e67d7SRamkumar Ramachandra void SlowDynamicAPInt::dump() const { print(dbgs()); }
287