GCC Code Coverage Report
Directory: . Exec Total Coverage
File: build-coverage/deps/include/symfpu/core/multiply.h Lines: 33 33 100.0 %
Date: 2021-09-18 Branches: 66 105 62.9 %

Line Exec Source
1
/*
2
** Copyright (C) 2018 Martin Brain
3
**
4
** See the file LICENSE for licensing information.
5
*/
6
7
/*
8
** multiply.h
9
**
10
** Martin Brain
11
** martin.brain@cs.ox.ac.uk
12
** 25/08/14
13
**
14
** Multiplication of arbitrary precision floats
15
**
16
*/
17
18
#include "symfpu/core/unpackedFloat.h"
19
#include "symfpu/core/ite.h"
20
#include "symfpu/core/rounder.h"
21
#include "symfpu/core/operations.h"
22
23
#ifndef SYMFPU_MULTIPLY
24
#define SYMFPU_MULTIPLY
25
26
namespace symfpu {
27
28
  // sign == multiplyResult.getSign() normally but not for FMA, thus an argument is needed
29
template <class t>
30
158
  unpackedFloat<t> addMultiplySpecialCases (const typename t::fpt &format,
31
					    const unpackedFloat<t> &left,
32
					    const unpackedFloat<t> &right,
33
					    const typename t::prop &sign,
34
					    const unpackedFloat<t> &multiplyResult) {
35
  typedef typename t::prop prop;
36
37
171
  prop eitherArgumentNan(left.getNaN() || right.getNaN());
38
345
  prop generateNan((left.getInf() && right.getZero()) ||
39
242
		   (left.getZero() && right.getInf()));
40
171
  prop isNan(eitherArgumentNan || generateNan);
41
42
171
  prop isInf(left.getInf() || right.getInf());
43
44
171
  prop isZero(left.getZero() || right.getZero());
45
46
  return ITE(isNan,
47
	     unpackedFloat<t>::makeNaN(format),
48
	     ITE(isInf,
49
		 unpackedFloat<t>::makeInf(format, sign),
50
		 ITE(isZero,
51
		     unpackedFloat<t>::makeZero(format, sign),
52
171
		     multiplyResult)));
53
 }
54
55
template <class t>
56
158
  unpackedFloat<t> arithmeticMultiply (const typename t::fpt &format,
57
				       const unpackedFloat<t> &left,
58
				       const unpackedFloat<t> &right) {
59
  typedef typename t::bwt bwt;
60
  typedef typename t::prop prop;
61
  typedef typename t::ubv ubv;
62
  typedef typename t::sbv sbv;
63
  typedef typename t::fpt fpt;
64
65
158
  PRECONDITION(left.valid(format));
66
158
  PRECONDITION(right.valid(format));
67
68
  // Compute sign
69
171
  prop multiplySign(left.getSign() ^ right.getSign());
70
71
  // Multiply the significands
72
316
  ubv significandProduct(expandingMultiply<t>(left.getSignificand(), right.getSignificand()));
73
  // Optimisation : low bits are not needed apart from the guard and sticky bits
74
  // Optimisation : top bits accurately predict whether re-alignment is needed
75
76
158
  bwt spWidth(significandProduct.getWidth());
77
316
  ubv topBit(significandProduct.extract(spWidth - 1, spWidth - 1));
78
316
  ubv nextBit(significandProduct.extract(spWidth - 2, spWidth - 2));
79
80
  // Alignment of inputs means at least one of the two MSB is 1
81
  //  i.e. [1,2) * [1,2) = [1,4)
82
  // topBitSet is the likely case
83
171
  prop topBitSet(topBit.isAllOnes());
84
158
  INVARIANT(topBitSet || nextBit.isAllOnes());
85
158
  probabilityAnnotation<t>(topBitSet, LIKELY);
86
87
  // Re-align
88
316
  ubv alignedSignificand(conditionalLeftShiftOne<t>(!topBitSet, significandProduct)); // Will not loose information
89
90
  // Add up exponents
91
  #if 0
92
  sbv exponentSum(expandingAdd<t>(left.getExponent(),right.getExponent()));
93
  sbv min(unpackedFloat<t>::minSubnormalExponent(format));
94
  sbv max(unpackedFloat<t>::maxNormalExponent(format));
95
  INVARIANT(expandingAdd<t>(min,min) <= exponentSum);
96
  INVARIANT(exponentSum <= expandingAdd<t>(max, max));
97
  // Optimisation : use the if-then-lazy-else to avoid multiplying for underflow and overflow
98
  //                subnormal * subnormal does not need to be evaluated
99
  //                may be best done in the rounder along with underflow
100
  #endif
101
102
316
  sbv alignedExponent(expandingAddWithCarryIn<t>(left.getExponent(),right.getExponent(), topBitSet));
103
104
105
  // Put back together
106
158
  fpt extendedFormat(format.exponentWidth() + 1, format.significandWidth() * 2);
107
158
  unpackedFloat<t> multiplyResult(extendedFormat, multiplySign, alignedExponent, alignedSignificand);
108
109
158
  POSTCONDITION(multiplyResult.valid(extendedFormat));
110
111
316
  return multiplyResult;
112
 }
113
114
115
// Put it all together...
116
template <class t>
117
158
  unpackedFloat<t> multiply (const typename t::fpt &format,
118
			     const typename t::rm &roundingMode,
119
			     const unpackedFloat<t> &left,
120
			     const unpackedFloat<t> &right) {
121
  //typedef typename t::bwt bwt;
122
  //typedef typename t::prop prop;
123
  //typedef typename t::ubv ubv;
124
  //typedef typename t::sbv sbv;
125
126
158
  PRECONDITION(left.valid(format));
127
158
  PRECONDITION(right.valid(format));
128
129
316
  unpackedFloat<t> multiplyResult(arithmeticMultiply(format, left, right));
130
131
316
  unpackedFloat<t> roundedMultiplyResult(rounder(format, roundingMode, multiplyResult));
132
133
158
  unpackedFloat<t> result(addMultiplySpecialCases(format, left, right, roundedMultiplyResult.getSign(), roundedMultiplyResult));
134
135
158
  POSTCONDITION(result.valid(format));
136
137
316
  return result;
138
 }
139
140
141
}
142
143
#endif
144