GCC Code Coverage Report
Directory: . Exec Total Coverage
File: deps/install/include/symfpu/core/multiply.h Lines: 33 33 100.0 %
Date: 2021-03-22 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
141
  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
150
  prop eitherArgumentNan(left.getNaN() || right.getNaN());
38
313
  prop generateNan((left.getInf() && right.getZero()) ||
39
223
		   (left.getZero() && right.getInf()));
40
150
  prop isNan(eitherArgumentNan || generateNan);
41
42
150
  prop isInf(left.getInf() || right.getInf());
43
44
150
  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
150
		     multiplyResult)));
53
 }
54
55
template <class t>
56
141
  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
141
  PRECONDITION(left.valid(format));
66
141
  PRECONDITION(right.valid(format));
67
68
  // Compute sign
69
150
  prop multiplySign(left.getSign() ^ right.getSign());
70
71
  // Multiply the significands
72
282
  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
141
  bwt spWidth(significandProduct.getWidth());
77
282
  ubv topBit(significandProduct.extract(spWidth - 1, spWidth - 1));
78
282
  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
150
  prop topBitSet(topBit.isAllOnes());
84
141
  INVARIANT(topBitSet || nextBit.isAllOnes());
85
141
  probabilityAnnotation<t>(topBitSet, LIKELY);
86
87
  // Re-align
88
282
  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
282
  sbv alignedExponent(expandingAddWithCarryIn<t>(left.getExponent(),right.getExponent(), topBitSet));
103
104
105
  // Put back together
106
141
  unpackedFloat<t> multiplyResult(multiplySign, alignedExponent, alignedSignificand);
107
108
109
141
  fpt extendedFormat(format.exponentWidth() + 1, format.significandWidth() * 2);
110
141
  POSTCONDITION(multiplyResult.valid(extendedFormat));
111
112
282
  return multiplyResult;
113
 }
114
115
116
// Put it all together...
117
template <class t>
118
141
  unpackedFloat<t> multiply (const typename t::fpt &format,
119
			     const typename t::rm &roundingMode,
120
			     const unpackedFloat<t> &left,
121
			     const unpackedFloat<t> &right) {
122
  //typedef typename t::bwt bwt;
123
  //typedef typename t::prop prop;
124
  //typedef typename t::ubv ubv;
125
  //typedef typename t::sbv sbv;
126
127
141
  PRECONDITION(left.valid(format));
128
141
  PRECONDITION(right.valid(format));
129
130
282
  unpackedFloat<t> multiplyResult(arithmeticMultiply(format, left, right));
131
132
282
  unpackedFloat<t> roundedMultiplyResult(rounder(format, roundingMode, multiplyResult));
133
134
141
  unpackedFloat<t> result(addMultiplySpecialCases(format, left, right, roundedMultiplyResult.getSign(), roundedMultiplyResult));
135
136
141
  POSTCONDITION(result.valid(format));
137
138
282
  return result;
139
 }
140
141
142
}
143
144
#endif
145