1 #pragma once
2 // posit_4_0.hpp: specialized 4-bit posit using lookup table arithmetic
3 //
4 // Copyright (C) 2017-2021 Supercomputing, Inc.
5 // First implementation: 2019
6 //
7 // This file is part of the universal numbers project, which is released under an MIT Open Source license.
8 
9 // DO NOT USE DIRECTLY!
10 // the compile guards in this file are only valid in the context of the specialization logic
11 // configured in the main <universal/posit/posit>
12 
13 #ifndef POSIT_FAST_POSIT_4_0
14 #define POSIT_FAST_POSIT_4_0 0
15 #endif
16 
17 namespace sw::universal {
18 
19 		// set the fast specialization variable to indicate that we are running a special template specialization
20 #if POSIT_FAST_POSIT_4_0
21 #ifdef _MSC_VER
22 #pragma message("Fast specialization of posit<4,0>")
23 //#else
24 //#warning("Fast specialization of posit<4,0>")
25 #endif
26 
27 constexpr uint8_t posit_4_0_addition_lookup[256] = {
28 	0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,
29 	1,2,3,4,4,6,6,7,8,9,10,12,13,14,15,0,
30 	2,3,4,4,5,6,6,7,8,9,11,12,14,15,0,1,
31 	3,4,4,5,6,6,6,7,8,9,12,13,15,0,1,2,
32 	4,4,5,6,6,6,6,7,8,10,12,14,0,1,2,3,
33 	5,6,6,6,6,6,7,7,8,10,14,0,2,3,4,4,
34 	6,6,6,6,6,7,7,7,8,10,0,2,4,4,5,6,
35 	7,7,7,7,7,7,7,7,8,0,6,6,6,7,7,7,
36 	8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
37 	9,9,9,9,10,10,10,0,8,9,9,9,9,9,9,9,
38 	10,10,11,12,12,14,0,6,8,9,9,9,10,10,10,10,
39 	11,12,12,13,14,0,2,6,8,9,9,10,10,10,10,10,
40 	12,13,14,15,0,2,4,6,8,9,10,10,10,10,11,12,
41 	13,14,15,0,1,3,4,7,8,9,10,10,10,11,12,12,
42 	14,15,0,1,2,4,5,7,8,9,10,10,11,12,12,13,
43 	15,0,1,2,3,4,6,7,8,9,10,10,12,12,13,14,
44 };
45 
46 constexpr uint8_t posit_4_0_subtraction_lookup[256] = {
47 	0,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,
48 	1,0,15,14,13,12,10,9,8,7,6,6,4,4,3,2,
49 	2,1,0,15,14,12,11,9,8,7,6,6,5,4,4,3,
50 	3,2,1,0,15,13,12,9,8,7,6,6,6,5,4,4,
51 	4,3,2,1,0,14,12,10,8,7,6,6,6,6,5,4,
52 	5,4,4,3,2,0,14,10,8,7,7,6,6,6,6,6,
53 	6,6,5,4,4,2,0,10,8,7,7,7,6,6,6,6,
54 	7,7,7,7,6,6,6,0,8,7,7,7,7,7,7,7,
55 	8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
56 	9,9,9,9,9,9,9,9,8,0,10,10,10,9,9,9,
57 	10,10,10,10,10,9,9,9,8,6,0,14,12,12,11,10,
58 	11,10,10,10,10,10,9,9,8,6,2,0,14,13,12,12,
59 	12,12,11,10,10,10,10,9,8,6,4,2,0,15,14,13,
60 	13,12,12,11,10,10,10,9,8,7,4,3,1,0,15,14,
61 	14,13,12,12,11,10,10,9,8,7,5,4,2,1,0,15,
62 	15,14,13,12,12,10,10,9,8,7,6,4,3,2,1,0,
63 };
64 
65 constexpr uint8_t posit_4_0_multiplication_lookup[256] = {
66 	0,0,0,0,0,0,0,0,8,0,0,0,0,0,0,0,
67 	0,1,1,1,1,2,2,4,8,12,14,14,15,15,15,15,
68 	0,1,1,2,2,3,4,6,8,10,12,13,14,14,15,15,
69 	0,1,2,2,3,4,5,6,8,10,11,12,13,14,14,15,
70 	0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,
71 	0,2,3,4,5,6,6,7,8,9,10,10,11,12,13,14,
72 	0,2,4,5,6,6,7,7,8,9,9,10,10,11,12,14,
73 	0,4,6,6,7,7,7,7,8,9,9,9,9,10,10,12,
74 	8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
75 	0,12,10,10,9,9,9,9,8,7,7,7,7,6,6,4,
76 	0,14,12,11,10,10,9,9,8,7,7,6,6,5,4,2,
77 	0,14,13,12,11,10,10,9,8,7,6,6,5,4,3,2,
78 	0,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,
79 	0,15,14,14,13,12,11,10,8,6,5,4,3,2,2,1,
80 	0,15,15,14,14,13,12,10,8,6,4,3,2,2,1,1,
81 	0,15,15,15,15,14,14,12,8,4,2,2,1,1,1,1,
82 };
83 
84 constexpr uint8_t posit_4_0_division_lookup[256] = {
85 	8,0,0,0,0,0,0,0,8,0,0,0,0,0,0,0,
86 	8,4,2,1,1,1,1,1,8,15,15,15,15,15,14,12,
87 	8,6,4,3,2,1,1,1,8,15,15,15,14,13,12,10,
88 	8,6,5,4,3,2,2,1,8,15,14,14,13,12,11,10,
89 	8,7,6,5,4,3,2,1,8,15,14,13,12,11,10,9,
90 	8,7,6,6,5,4,3,2,8,14,13,12,11,10,10,9,
91 	8,7,7,6,6,5,4,2,8,14,12,11,10,10,9,9,
92 	8,7,7,7,7,6,6,4,8,12,10,10,9,9,9,9,
93 	8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
94 	8,9,9,9,9,10,10,12,8,4,6,6,7,7,7,7,
95 	8,9,9,10,10,11,12,14,8,2,4,5,6,6,7,7,
96 	8,9,10,10,11,12,13,14,8,2,3,4,5,6,6,7,
97 	8,9,10,11,12,13,14,15,8,1,2,3,4,5,6,7,
98 	8,10,11,12,13,14,14,15,8,1,2,2,3,4,5,6,
99 	8,10,12,13,14,15,15,15,8,1,1,1,2,3,4,6,
100 	8,12,14,15,15,15,15,15,8,1,1,1,1,1,2,4,
101 };
102 
103 constexpr uint8_t posit_4_0_reciprocal_lookup[16] = {
104 	8,7,6,5,4,3,2,1,8,15,14,13,12,11,10,9,
105 };
106 
107 template<>
108 class posit<NBITS_IS_4, ES_IS_0> {
109 public:
110 	static constexpr size_t nbits = NBITS_IS_4;
111 	static constexpr size_t es = ES_IS_0;
112 	static constexpr size_t sbits = 1;
113 	static constexpr size_t rbits = nbits - sbits;
114 	static constexpr size_t ebits = es;
115 	static constexpr size_t fbits = nbits - 3;
116 	static constexpr size_t fhbits = fbits + 1;
117 	static constexpr uint8_t index_shift = 4;
118 	static constexpr uint8_t bit_mask = 0x0F;
119 	static constexpr uint8_t nar_encoding = 0x08;
120 	static constexpr uint8_t one_encoding = 0x04; // 0100
121 	static constexpr uint8_t minusone_encoding = 0x0C; // 1100
122 
posit()123 	posit() { _bits = 0; }
124 	posit(const posit&) = default;
125 	posit(posit&&) = default;
126 	posit& operator=(const posit&) = default;
127 	posit& operator=(posit&&) = default;
128 
129 	// specific value constructor
posit(const SpecificValue code)130 	constexpr posit(const SpecificValue code) : _bits(0) {
131 		switch (code) {
132 		case SpecificValue::infpos:
133 		case SpecificValue::maxpos:
134 			maxpos();
135 			break;
136 		case SpecificValue::minpos:
137 			minpos();
138 			break;
139 		case SpecificValue::zero:
140 		default:
141 			zero();
142 			break;
143 		case SpecificValue::minneg:
144 			minneg();
145 			break;
146 		case SpecificValue::infneg:
147 		case SpecificValue::maxneg:
148 			maxneg();
149 			break;
150 		case SpecificValue::qnan:
151 		case SpecificValue::snan:
152 		case SpecificValue::nar:
153 			setnar();
154 			break;
155 		}
156 	}
157 
posit(signed char initial_value)158 	explicit posit(signed char initial_value) { *this = (long long)initial_value; }
posit(short initial_value)159 	explicit posit(short initial_value) { *this = (long long)initial_value; }
posit(int initial_value)160 	explicit posit(int initial_value) { *this = (long long)initial_value; }
posit(long int initial_value)161 	explicit posit(long int initial_value) { *this = (long long)initial_value; }
posit(long long initial_value)162 				posit(long long initial_value) { *this = (long long)initial_value; }
posit(char initial_value)163 	explicit posit(char initial_value) { *this = (long long)initial_value; }
posit(unsigned short initial_value)164 	explicit posit(unsigned short initial_value) { *this = (long long)initial_value; }
posit(unsigned int initial_value)165 	explicit posit(unsigned int initial_value) { *this = (long long)initial_value; }
posit(unsigned long int initial_value)166 	explicit posit(unsigned long int initial_value) { *this = (long long)initial_value; }
posit(unsigned long long initial_value)167 	explicit posit(unsigned long long initial_value) { *this = (long long)initial_value; }
posit(float initial_value)168 	explicit posit(float initial_value) { *this = initial_value; }
posit(double initial_value)169 	explicit posit(double initial_value) { *this = initial_value; }
posit(long double initial_value)170 	explicit posit(long double initial_value) { *this = initial_value; }
171 
172 	// assignment operators for native types
operator =(int rhs)173 	posit& operator=(int rhs) {
174 		return operator=((long long)(rhs));
175 	}
operator =(long int rhs)176 	posit& operator=(long int rhs) {
177 		return operator=((long long)(rhs));
178 	}
operator =(long long rhs)179 	posit& operator=(long long rhs) {
180 		// only valid integers are -4, -2, -1, 0, 1, 2, 4
181 		_bits = uint8_t(0);
182 		if (rhs <= -4) {
183 			_bits = 0x9;   // value is -4, or -maxpos
184 		}
185 		else if (-4 > rhs && rhs <= -2) {
186 			_bits = 0xA;   // value is -2
187 		}
188 		else if (-2 > rhs && rhs <= -1) {
189 			_bits = 0xC;   // value is -1
190 		}
191 		else if (-1 > rhs && rhs < 1) {
192 			_bits = 0x0;   // value is 0
193 		}
194 		else if (1 <= rhs && rhs < 2) {
195 			_bits = 0x4;   // value is 1
196 		}
197 		else if (2 <= rhs && rhs < 4) {
198 			_bits = 0x6;   // value is 2
199 		}
200 		else if (4 <= rhs) {
201 			_bits = 0x7;   // value is 4, or maxpos
202 		}
203 		return *this;
204 	}
operator =(const float rhs)205 	posit& operator=(const float rhs) {
206 		return float_assign(rhs);
207 	}
operator =(const double rhs)208 	posit& operator=(const double rhs) {
209 		return float_assign(rhs);
210 	}
operator =(const long double rhs)211 	posit& operator=(const long double rhs) {
212 		return float_assign(rhs);
213 	}
214 
operator long double() const215 	explicit operator long double() const { return to_long_double(); }
operator double() const216 	explicit operator double() const { return to_double(); }
operator float() const217 	explicit operator float() const { return to_float(); }
operator long long() const218 	explicit operator long long() const { return to_long_long(); }
operator long() const219 	explicit operator long() const { return to_long(); }
operator int() const220 	explicit operator int() const { return to_int(); }
operator unsigned long long() const221 	explicit operator unsigned long long() const { return to_long_long(); }
operator unsigned long() const222 	explicit operator unsigned long() const { return to_long(); }
operator unsigned int() const223 	explicit operator unsigned int() const { return to_int(); }
224 
setBitblock(sw::universal::bitblock<NBITS_IS_4> & raw)225 	posit& setBitblock(sw::universal::bitblock<NBITS_IS_4>& raw) {
226 		_bits = uint8_t(raw.to_ulong());
227 		return *this;
228 	}
setbits(uint64_t value)229 	posit& setbits(uint64_t value) {
230 		_bits = uint8_t(value & bit_mask);
231 		return *this;
232 	}
operator -() const233 	posit operator-() const {
234 		if (iszero()) {
235 			return *this;
236 		}
237 		if (isnar()) {
238 			return *this;
239 		}
240 		posit p;
241 		return p.setbits((~_bits) + 1);
242 	}
operator +=(const posit & b)243 	posit& operator+=(const posit& b) {
244 		uint16_t index = (_bits << index_shift) | b._bits;
245 		_bits = posit_4_0_addition_lookup[index];
246 		return *this;
247 	}
operator -=(const posit & b)248 	posit& operator-=(const posit& b) {
249 		uint16_t index = (_bits << index_shift) | b._bits;
250 		_bits = posit_4_0_subtraction_lookup[index];
251 		return *this;
252 	}
operator *=(const posit & b)253 	posit& operator*=(const posit& b) {
254 		uint16_t index = (_bits << index_shift) | b._bits;
255 		_bits = posit_4_0_multiplication_lookup[index];
256 		return *this;
257 	}
operator /=(const posit & b)258 	posit& operator/=(const posit& b) {
259 		uint16_t index = (_bits << index_shift) | b._bits;
260 		_bits = posit_4_0_division_lookup[index];
261 		return *this;
262 	}
operator ++()263 	posit& operator++() {
264 		_bits = (_bits + 1) & bit_mask;
265 		return *this;
266 	}
operator ++(int)267 	posit operator++(int) {
268 		posit tmp(*this);
269 		operator++();
270 		return tmp;
271 	}
operator --()272 	posit& operator--() {
273 		_bits = (_bits - 1) & bit_mask;
274 		return *this;
275 	}
operator --(int)276 	posit operator--(int) {
277 		posit tmp(*this);
278 		operator--();
279 		return tmp;
280 	}
reciprocate() const281 	posit reciprocate() const {
282 		posit p;
283 		p.setbits(posit_4_0_reciprocal_lookup[_bits]);
284 		return p;
285 	}
286 	// SELECTORS
sign() const287 	inline bool sign()   const { return bool(_bits & 0x08u); }
isnar() const288 	inline bool isnar()  const { return (_bits == nar_encoding); }
iszero() const289 	inline bool iszero() const { return (_bits == 0); }
isone() const290 	inline bool isone() const { // pattern 0100....
291 		return (_bits == one_encoding);
292 	}
isminusone() const293 	inline bool isminusone() const { // pattern 1100...
294 		return (_bits == minusone_encoding);
295 	}
isneg() const296 	inline bool isneg()      const { return bool(_bits & 0x08u); }
ispos() const297 	inline bool ispos()      const { return !isneg(); }
ispowerof2() const298 	inline bool ispowerof2() const { return !(_bits & 0x1u); }
299 
sign_value() const300 	inline int sign_value() const { return (_bits & 0x08u ? -1 : 1); }
301 
get() const302 	bitblock<NBITS_IS_4> get() const { bitblock<NBITS_IS_4> bb; bb = int(_bits & bit_mask); return bb; }
encoding() const303 	unsigned int encoding() const { return (unsigned int)(_bits & bit_mask); }
304 
clear()305 	inline void clear() { _bits = 0; }
setzero()306 	inline void setzero() { clear(); }
setnar()307 	inline void setnar() { _bits = nar_encoding; }
minpos()308 	inline posit& minpos() {
309 		clear();
310 		return ++(*this);
311 	}
maxpos()312 	inline posit& maxpos() {
313 		setnar();
314 		return --(*this);
315 	}
zero()316 	inline posit& zero() {
317 		clear();
318 		return *this;
319 	}
minneg()320 	inline posit& minneg() {
321 		clear();
322 		return --(*this);
323 	}
maxneg()324 	inline posit& maxneg() {
325 		setnar();
326 		return ++(*this);
327 	}
328 private:
329 	uint8_t _bits;
330 
331 	// Conversion functions
332 #if POSIT_THROW_ARITHMETIC_EXCEPTION
to_int() const333 	int         to_int() const {
334 		if (iszero()) return 0;
335 		if (isnar()) throw posit_nar{};
336 		return int(to_float());
337 	}
to_long() const338 	long        to_long() const {
339 		if (iszero()) return 0;
340 		if (isnar()) throw posit_nar{};
341 		return long(to_double());
342 	}
to_long_long() const343 	long long   to_long_long() const {
344 		if (iszero()) return 0;
345 		if (isnar()) throw posit_nar{};
346 		return long(to_long_double());
347 	}
348 #else
to_int() const349 	int         to_int() const {
350 		if (iszero()) return 0;
351 		if (isnar())  return int(INFINITY);
352 		return int(to_float());
353 	}
to_long() const354 	long        to_long() const {
355 		if (iszero()) return 0;
356 		if (isnar())  return long(INFINITY);
357 		return long(to_double());
358 	}
to_long_long() const359 	long long   to_long_long() const {
360 		if (iszero()) return 0;
361 		if (isnar())  return (long long)(INFINITY);
362 		return long(to_long_double());
363 	}
364 #endif
to_float() const365 	float       to_float() const {
366 		return (float)to_double();
367 	}
to_double() const368 	double      to_double() const {
369 		if (iszero())	return 0.0;
370 		if (isnar())	return NAN;
371 		bool		     	 _sign;
372 		regime<nbits, es>    _regime;
373 		exponent<nbits, es>  _exponent;
374 		fraction<fbits>      _fraction;
375 		bitblock<nbits>		 _raw_bits;
376 		_raw_bits.reset();
377 		uint64_t mask = 1;
378 		for (size_t i = 0; i < nbits; i++) {
379 			_raw_bits.set(i, (_bits & mask));
380 			mask <<= 1;
381 		}
382 		decode(_raw_bits, _sign, _regime, _exponent, _fraction);
383 		double s = (_sign ? -1.0 : 1.0);
384 		double r = _regime.value();
385 		double e = _exponent.value();
386 		double f = (1.0 + _fraction.value());
387 		return s * r * e * f;
388 	}
to_long_double() const389 	long double to_long_double() const {
390 		if (iszero())  return 0.0;
391 		if (isnar())   return NAN;
392 		bool		     	 _sign;
393 		regime<nbits, es>    _regime;
394 		exponent<nbits, es>  _exponent;
395 		fraction<fbits>      _fraction;
396 		bitblock<nbits>		 _raw_bits;
397 		_raw_bits.reset();
398 		uint64_t mask = 1;
399 		for (size_t i = 0; i < nbits; i++) {
400 			_raw_bits.set(i, (_bits & mask));
401 			mask <<= 1;
402 		}
403 		decode(_raw_bits, _sign, _regime, _exponent, _fraction);
404 		long double s = (_sign ? -1.0 : 1.0);
405 		long double r = _regime.value();
406 		long double e = _exponent.value();
407 		long double f = (1.0 + _fraction.value());
408 		return s * r * e * f;
409 	}
410 
411 	template <typename T>
float_assign(const T & rhs)412 	posit& float_assign(const T& rhs) {
413 		constexpr int dfbits = std::numeric_limits<T>::digits - 1;
414 		internal::value<dfbits> v((T)rhs);
415 
416 		// special case processing
417 		if (v.iszero()) {
418 			setzero();
419 			return *this;
420 		}
421 		if (v.isinf() || v.isnan()) {  // posit encode for FP_INFINITE and NaN as NaR (Not a Real)
422 			setnar();
423 			return *this;
424 		}
425 		bitblock<NBITS_IS_4> ptt;
426 		convert_to_bb<NBITS_IS_4, ES_IS_0, dfbits>(v.sign(), v.scale(), v.fraction(), ptt); // TODO: needs to be faster
427 		_bits = uint8_t(ptt.to_ulong());
428 		return *this;
429 	}
430 
431 	// I/O operators
432 	friend std::ostream& operator<< (std::ostream& ostr, const posit<NBITS_IS_4, ES_IS_0>& p);
433 	friend std::istream& operator>> (std::istream& istr, posit<NBITS_IS_4, ES_IS_0>& p);
434 
435 	// posit - posit logic functions
436 	friend bool operator==(const posit<NBITS_IS_4, ES_IS_0>& lhs, const posit<NBITS_IS_4, ES_IS_0>& rhs);
437 	friend bool operator!=(const posit<NBITS_IS_4, ES_IS_0>& lhs, const posit<NBITS_IS_4, ES_IS_0>& rhs);
438 	friend bool operator< (const posit<NBITS_IS_4, ES_IS_0>& lhs, const posit<NBITS_IS_4, ES_IS_0>& rhs);
439 	friend bool operator> (const posit<NBITS_IS_4, ES_IS_0>& lhs, const posit<NBITS_IS_4, ES_IS_0>& rhs);
440 	friend bool operator<=(const posit<NBITS_IS_4, ES_IS_0>& lhs, const posit<NBITS_IS_4, ES_IS_0>& rhs);
441 	friend bool operator>=(const posit<NBITS_IS_4, ES_IS_0>& lhs, const posit<NBITS_IS_4, ES_IS_0>& rhs);
442 
443 };
444 
445 // posit I/O operators
446 // generate a posit format ASCII format nbits.esxNN...NNp
operator <<(std::ostream & ostr,const posit<NBITS_IS_4,ES_IS_0> & p)447 inline std::ostream& operator<<(std::ostream& ostr, const posit<NBITS_IS_4, ES_IS_0>& p) {
448 	// to make certain that setw and left/right operators work properly
449 	// we need to transform the posit into a string
450 	std::stringstream ss;
451 #if POSIT_ROUNDING_ERROR_FREE_IO_FORMAT
452 	ss << NBITS_IS_4 << '.' << ES_IS_0 << 'x' << to_hex(p.get()) << 'p';
453 #else
454 	std::streamsize prec = ostr.precision();
455 	std::streamsize width = ostr.width();
456 	std::ios_base::fmtflags ff;
457 	ff = ostr.flags();
458 	ss.flags(ff);
459 	ss << std::showpos << std::setw(width) << std::setprecision(prec) << (long double)p;
460 #endif
461 	return ostr << ss.str();
462 }
463 
464 // read an ASCII float or posit format: nbits.esxNN...NNp, for example: 32.2x80000000p
operator >>(std::istream & istr,posit<NBITS_IS_4,ES_IS_0> & p)465 inline std::istream& operator>> (std::istream& istr, posit<NBITS_IS_4, ES_IS_0>& p) {
466 	std::string txt;
467 	istr >> txt;
468 	if (!parse(txt, p)) {
469 		std::cerr << "unable to parse -" << txt << "- into a posit value\n";
470 	}
471 	return istr;
472 }
473 
474 // convert a posit value to a string using "nar" as designation of NaR
to_string(const posit<NBITS_IS_4,ES_IS_0> & p,std::streamsize precision)475 inline std::string to_string(const posit<NBITS_IS_4, ES_IS_0>& p, std::streamsize precision) {
476 	if (p.isnar()) {
477 		return std::string("nar");
478 	}
479 	std::stringstream ss;
480 	ss << std::setprecision(precision) << float(p);
481 	return ss.str();
482 }
483 
484 // posit - posit binary logic operators
operator ==(const posit<NBITS_IS_4,ES_IS_0> & lhs,const posit<NBITS_IS_4,ES_IS_0> & rhs)485 inline bool operator==(const posit<NBITS_IS_4, ES_IS_0>& lhs, const posit<NBITS_IS_4, ES_IS_0>& rhs) {
486 	return lhs._bits == rhs._bits;
487 }
operator !=(const posit<NBITS_IS_4,ES_IS_0> & lhs,const posit<NBITS_IS_4,ES_IS_0> & rhs)488 inline bool operator!=(const posit<NBITS_IS_4, ES_IS_0>& lhs, const posit<NBITS_IS_4, ES_IS_0>& rhs) {
489 	return !operator==(lhs, rhs);
490 }
operator <(const posit<NBITS_IS_4,ES_IS_0> & lhs,const posit<NBITS_IS_4,ES_IS_0> & rhs)491 inline bool operator< (const posit<NBITS_IS_4, ES_IS_0>& lhs, const posit<NBITS_IS_4, ES_IS_0>& rhs) {
492 	if (rhs.isnar()) {
493 		return false;
494 	}
495 	posit<NBITS_IS_4, ES_IS_0> r = lhs - rhs;  // else calculate the difference and check if negative
496 	return r.isneg();
497 }
operator >(const posit<NBITS_IS_4,ES_IS_0> & lhs,const posit<NBITS_IS_4,ES_IS_0> & rhs)498 inline bool operator> (const posit<NBITS_IS_4, ES_IS_0>& lhs, const posit<NBITS_IS_4, ES_IS_0>& rhs) {
499 	return operator< (rhs, lhs);
500 }
operator <=(const posit<NBITS_IS_4,ES_IS_0> & lhs,const posit<NBITS_IS_4,ES_IS_0> & rhs)501 inline bool operator<=(const posit<NBITS_IS_4, ES_IS_0>& lhs, const posit<NBITS_IS_4, ES_IS_0>& rhs) {
502 	return operator< (lhs, rhs) || operator==(lhs, rhs);
503 }
operator >=(const posit<NBITS_IS_4,ES_IS_0> & lhs,const posit<NBITS_IS_4,ES_IS_0> & rhs)504 inline bool operator>=(const posit<NBITS_IS_4, ES_IS_0>& lhs, const posit<NBITS_IS_4, ES_IS_0>& rhs) {
505 	return !operator< (lhs, rhs);
506 }
507 
operator +(const posit<NBITS_IS_4,ES_IS_0> & lhs,const posit<NBITS_IS_4,ES_IS_0> & rhs)508 inline posit<NBITS_IS_4, ES_IS_0> operator+(const posit<NBITS_IS_4, ES_IS_0>& lhs, const posit<NBITS_IS_4, ES_IS_0>& rhs) {
509 	posit<NBITS_IS_4, ES_IS_0> sum = lhs;
510 	sum += rhs;
511 	return sum;
512 }
513 
514 #endif // POSIT_FAST_POSIT_4_0
515 
516 } // namespace sw::universal
517