• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2006 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef Sk64_DEFINED
18 #define Sk64_DEFINED
19 
20 #include "SkFixed.h"
21 #include "SkMath.h"
22 
23 /** \class Sk64
24 
25     Sk64 is a 64-bit math package that does not require long long support from the compiler.
26 */
27 struct Sk64 {
28     int32_t  fHi;   //!< the high 32 bits of the number (including sign)
29     uint32_t fLo;   //!< the low 32 bits of the number
30 
31     /** Returns non-zero if the Sk64 can be represented as a signed 32 bit integer
32     */
is32Sk6433     SkBool is32() const { return fHi == ((int32_t)fLo >> 31); }
34 
35     /** Returns non-zero if the Sk64 cannot be represented as a signed 32 bit integer
36     */
is64Sk6437     SkBool is64() const { return fHi != ((int32_t)fLo >> 31); }
38 
39     /** Returns non-zero if the Sk64 can be represented as a signed 48 bit integer. Used to know
40         if we can shift the value down by 16 to treat it as a SkFixed.
41     */
42     SkBool isFixed() const;
43 
44     /** Return the signed 32 bit integer equivalent. Asserts that is32() returns non-zero.
45     */
get32Sk6446     int32_t get32() const { SkASSERT(this->is32()); return (int32_t)fLo; }
47 
48     /** Return the number >> 16. Asserts that this does not loose any significant high bits.
49     */
getFixedSk6450     SkFixed getFixed() const {
51         SkASSERT(this->isFixed());
52 
53         uint32_t sum = fLo + (1 << 15);
54         int32_t  hi = fHi;
55         if (sum < fLo) {
56             hi += 1;
57         }
58         return (hi << 16) | (sum >> 16);
59     }
60 
61     /** Return the number >> 30. Asserts that this does not loose any
62         significant high bits.
63     */
64     SkFract getFract() const;
65 
66     /** Returns the square-root of the number as a signed 32 bit value. */
67     int32_t getSqrt() const;
68 
69     /** Returns the number of leading zeros of the absolute value of this.
70         Will return in the range [0..64]
71     */
72     int getClzAbs() const;
73 
74     /** Returns non-zero if the number is zero */
isZeroSk6475     SkBool  isZero() const { return (fHi | fLo) == 0; }
76 
77     /** Returns non-zero if the number is non-zero */
nonZeroSk6478     SkBool  nonZero() const { return fHi | fLo; }
79 
80     /** Returns non-zero if the number is negative (number < 0) */
isNegSk6481     SkBool  isNeg() const { return (uint32_t)fHi >> 31; }
82 
83     /** Returns non-zero if the number is positive (number > 0) */
isPosSk6484     SkBool  isPos() const { return ~(fHi >> 31) & (fHi | fLo); }
85 
86     /** Returns -1,0,+1 based on the sign of the number */
getSignSk6487     int     getSign() const { return (fHi >> 31) | Sk32ToBool(fHi | fLo); }
88 
89     /** Negate the number */
90     void    negate();
91 
92     /** If the number < 0, negate the number
93     */
94     void    abs();
95 
96     /** Returns the number of bits needed to shift the Sk64 to the right
97         in order to make it fit in a signed 32 bit integer.
98     */
99     int     shiftToMake32() const;
100 
101     /** Set the number to zero */
setZeroSk64102     void    setZero() { fHi = fLo = 0; }
103 
104     /** Set the high and low 32 bit values of the number */
setSk64105     void    set(int32_t hi, uint32_t lo) { fHi = hi; fLo = lo; }
106 
107     /** Set the number to the specified 32 bit integer */
setSk64108     void    set(int32_t a) { fHi = a >> 31; fLo = a; }
109 
110     /** Set the number to the product of the two 32 bit integers */
111     void    setMul(int32_t a, int32_t b);
112 
113     /** extract 32bits after shifting right by bitCount.
114         Note: itCount must be [0..63].
115         Asserts that no significant high bits were lost.
116     */
117     int32_t getShiftRight(unsigned bitCount) const;
118 
119     /** Shift the number left by the specified number of bits.
120         @param bits How far to shift left, must be [0..63]
121     */
122     void    shiftLeft(unsigned bits);
123 
124     /** Shift the number right by the specified number of bits.
125         @param bits How far to shift right, must be [0..63]. This
126         performs an arithmetic right-shift (sign extending).
127     */
128     void    shiftRight(unsigned bits);
129 
130     /** Shift the number right by the specified number of bits, but
131         round the result.
132         @param bits How far to shift right, must be [0..63]. This
133         performs an arithmetic right-shift (sign extending).
134     */
135     void    roundRight(unsigned bits);
136 
137     /** Add the specified 32 bit integer to the number */
addSk64138     void add(int32_t lo) {
139         int32_t  hi = lo >> 31; // 0 or -1
140         uint32_t sum = fLo + (uint32_t)lo;
141 
142         fHi = fHi + hi + (sum < fLo);
143         fLo = sum;
144     }
145 
146     /** Add the specified Sk64 to the number */
addSk64147     void add(int32_t hi, uint32_t lo) {
148         uint32_t sum = fLo + lo;
149 
150         fHi = fHi + hi + (sum < fLo);
151         fLo = sum;
152     }
153 
154     /** Add the specified Sk64 to the number */
addSk64155     void    add(const Sk64& other) { this->add(other.fHi, other.fLo); }
156 
157     /** Subtract the specified Sk64 from the number. (*this) = (*this) - num
158     */
159     void    sub(const Sk64& num);
160 
161     /** Subtract the number from the specified Sk64. (*this) = num - (*this)
162     */
163     void    rsub(const Sk64& num);
164 
165     /** Multiply the number by the specified 32 bit integer
166     */
167     void    mul(int32_t);
168 
169     enum DivOptions {
170         kTrunc_DivOption,   //!< truncate the result when calling div()
171         kRound_DivOption    //!< round the result when calling div()
172     };
173 
174     /** Divide the number by the specified 32 bit integer, using the specified
175         divide option (either truncate or round).
176     */
177     void    div(int32_t, DivOptions);
178 
179     /** return (this + other >> 16) as a 32bit result */
addGetFixedSk64180     SkFixed addGetFixed(const Sk64& other) const {
181         return this->addGetFixed(other.fHi, other.fLo);
182     }
183 
184     /** return (this + Sk64(hi, lo) >> 16) as a 32bit result */
addGetFixedSk64185     SkFixed addGetFixed(int32_t hi, uint32_t lo) const {
186 #ifdef SK_DEBUG
187         Sk64    tmp(*this);
188         tmp.add(hi, lo);
189 #endif
190 
191         uint32_t sum = fLo + lo;
192         hi += fHi + (sum < fLo);
193         lo = sum;
194 
195         sum = lo + (1 << 15);
196         if (sum < lo)
197             hi += 1;
198 
199         hi = (hi << 16) | (sum >> 16);
200         SkASSERT(hi == tmp.getFixed());
201         return hi;
202     }
203 
204     /** Return the result of dividing the number by denom, treating the answer
205         as a SkFixed. (*this) << 16 / denom. It is an error for denom to be 0.
206     */
207     SkFixed getFixedDiv(const Sk64& denom) const;
208 
209     friend bool operator==(const Sk64& a, const Sk64& b) {
210         return a.fHi == b.fHi && a.fLo == b.fLo;
211     }
212 
213     friend bool operator!=(const Sk64& a, const Sk64& b) {
214         return a.fHi != b.fHi || a.fLo != b.fLo;
215     }
216 
217     friend bool operator<(const Sk64& a, const Sk64& b) {
218         return a.fHi < b.fHi || (a.fHi == b.fHi && a.fLo < b.fLo);
219     }
220 
221     friend bool operator<=(const Sk64& a, const Sk64& b) {
222         return a.fHi < b.fHi || (a.fHi == b.fHi && a.fLo <= b.fLo);
223     }
224 
225     friend bool operator>(const Sk64& a, const Sk64& b) {
226         return a.fHi > b.fHi || (a.fHi == b.fHi && a.fLo > b.fLo);
227     }
228 
229     friend bool operator>=(const Sk64& a, const Sk64& b) {
230         return a.fHi > b.fHi || (a.fHi == b.fHi && a.fLo >= b.fLo);
231     }
232 
233 #ifdef SkLONGLONG
234     SkLONGLONG getLongLong() const;
235 #endif
236 };
237 
238 #endif
239 
240