FixedPoint.h revision 344779
1//===- FixedPoint.h - Fixed point constant handling -------------*- C++ -*-===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10/// \file
11/// Defines the fixed point number interface.
12/// This is a class for abstracting various operations performed on fixed point
13/// types described in ISO/IEC JTC1 SC22 WG14 N1169 starting at clause 4.
14//
15//===----------------------------------------------------------------------===//
16
17#ifndef LLVM_CLANG_BASIC_FIXEDPOINT_H
18#define LLVM_CLANG_BASIC_FIXEDPOINT_H
19
20#include "llvm/ADT/APSInt.h"
21
22namespace clang {
23
24class ASTContext;
25class QualType;
26
27/// The fixed point semantics work similarly to llvm::fltSemantics. The width
28/// specifies the whole bit width of the underlying scaled integer (with padding
29/// if any). The scale represents the number of fractional bits in this type.
30/// When HasUnsignedPadding is true and this type is signed, the first bit
31/// in the value this represents is treaded as padding.
32class FixedPointSemantics {
33public:
34  FixedPointSemantics(unsigned Width, unsigned Scale, bool IsSigned,
35                      bool IsSaturated, bool HasUnsignedPadding)
36      : Width(Width), Scale(Scale), IsSigned(IsSigned),
37        IsSaturated(IsSaturated), HasUnsignedPadding(HasUnsignedPadding) {
38    assert(Width >= Scale && "Not enough room for the scale");
39  }
40
41  unsigned getWidth() const { return Width; }
42  unsigned getScale() const { return Scale; }
43  bool isSigned() const { return IsSigned; }
44  bool isSaturated() const { return IsSaturated; }
45  bool hasUnsignedPadding() const { return HasUnsignedPadding; }
46
47  void setSaturated(bool Saturated) { IsSaturated = Saturated; }
48
49  unsigned getIntegralBits() const {
50    if (IsSigned || (!IsSigned && HasUnsignedPadding))
51      return Width - Scale - 1;
52    else
53      return Width - Scale;
54  }
55
56private:
57  unsigned Width;
58  unsigned Scale;
59  bool IsSigned;
60  bool IsSaturated;
61  bool HasUnsignedPadding;
62};
63
64/// The APFixedPoint class works similarly to APInt/APSInt in that it is a
65/// functional replacement for a scaled integer. It is meant to replicate the
66/// fixed point types proposed in ISO/IEC JTC1 SC22 WG14 N1169. The class carries
67/// info about the fixed point type's width, sign, scale, and saturation, and
68/// provides different operations that would normally be performed on fixed point
69/// types.
70///
71/// Semantically this does not represent any existing C type other than fixed
72/// point types and should eventually be moved to LLVM if fixed point types gain
73/// native IR support.
74class APFixedPoint {
75 public:
76   APFixedPoint(const llvm::APInt &Val, const FixedPointSemantics &Sema)
77       : Val(Val, !Sema.isSigned()), Sema(Sema) {
78     assert(Val.getBitWidth() == Sema.getWidth() &&
79            "The value should have a bit width that matches the Sema width");
80   }
81
82   APFixedPoint(uint64_t Val, const FixedPointSemantics &Sema)
83       : APFixedPoint(llvm::APInt(Sema.getWidth(), Val, Sema.isSigned()),
84                      Sema) {}
85
86   llvm::APSInt getValue() const { return llvm::APSInt(Val, !Sema.isSigned()); }
87   inline unsigned getWidth() const { return Sema.getWidth(); }
88   inline unsigned getScale() const { return Sema.getScale(); }
89   inline bool isSaturated() const { return Sema.isSaturated(); }
90   inline bool isSigned() const { return Sema.isSigned(); }
91   inline bool hasPadding() const { return Sema.hasUnsignedPadding(); }
92
93   // Convert this number to match the semantics provided.
94   APFixedPoint convert(const FixedPointSemantics &DstSema) const;
95
96   APFixedPoint shr(unsigned Amt) const {
97     return APFixedPoint(Val >> Amt, Sema);
98  }
99
100  APFixedPoint shl(unsigned Amt) const {
101    return APFixedPoint(Val << Amt, Sema);
102  }
103
104  llvm::APSInt getIntPart() const {
105    if (Val < 0 && Val != -Val) // Cover the case when we have the min val
106      return -(-Val >> getScale());
107    else
108      return Val >> getScale();
109  }
110
111  // If LHS > RHS, return 1. If LHS == RHS, return 0. If LHS < RHS, return -1.
112  int compare(const APFixedPoint &Other) const;
113  bool operator==(const APFixedPoint &Other) const {
114    return compare(Other) == 0;
115  }
116  bool operator!=(const APFixedPoint &Other) const {
117    return compare(Other) != 0;
118  }
119  bool operator>(const APFixedPoint &Other) const { return compare(Other) > 0; }
120  bool operator<(const APFixedPoint &Other) const { return compare(Other) < 0; }
121  bool operator>=(const APFixedPoint &Other) const {
122    return compare(Other) >= 0;
123  }
124  bool operator<=(const APFixedPoint &Other) const {
125    return compare(Other) <= 0;
126  }
127
128  static APFixedPoint getMax(const FixedPointSemantics &Sema);
129  static APFixedPoint getMin(const FixedPointSemantics &Sema);
130
131private:
132  llvm::APSInt Val;
133  FixedPointSemantics Sema;
134};
135
136}  // namespace clang
137
138#endif
139