2121 * Floating-point traits and functions *
2222 ***************************************/
2323
24+ namespace fp {
25+
2426/* *
2527 * @brief Traits describing IEEE-754 layout properties for a floating-point type.
2628 *
@@ -67,6 +69,8 @@ int getStoredFloatingPointExponent(fp_t value) {
6769 std::max (std::numeric_limits<fp_t >::min_exponent, std::ilogb (std::abs (value)) + 1 );
6870}
6971
72+ } // namespace fp
73+
7074/* *****************************
7175 * Global configuration enums *
7276 ******************************/
@@ -83,6 +87,8 @@ enum class normalisationDimension {
8387 * Matrix view *
8488 ***************/
8589
90+ namespace matrix {
91+
8692/* *
8793 * @brief Enum to specify the layout of the matrix in memory.
8894 */
@@ -284,6 +290,8 @@ MatrixView<const value_t> makeConstMatrixView(MatrixView<value_t> view) {
284290 return MatrixView<const value_t >(view.data , view.rows , view.cols , view.layout );
285291}
286292
293+ } // namespace matrix
294+
287295/* **********************
288296 * Multiterm emulation *
289297 ***********************/
@@ -412,8 +420,8 @@ struct DerivedParameters {
412420 * @throws std::invalid_argument if any runtime constraint is violated.
413421 */
414422template <typename fp_t , typename splitint_t , typename accumulator_t >
415- DerivedParameters deriveParameters (MatrixView<const fp_t > A,
416- MatrixView<const fp_t > B,
423+ DerivedParameters deriveParameters (matrix:: MatrixView<const fp_t > A,
424+ matrix:: MatrixView<const fp_t > B,
417425 const config& config) {
418426
419427 // Compile-time type checks.
@@ -501,7 +509,7 @@ struct OperandPreparationConfig {
501509 */
502510template <typename splitint_t , typename fp_t >
503511struct preparedOperand {
504- MatrixView<const fp_t > matrix; // /< View of original matrix.
512+ matrix:: MatrixView<const fp_t > matrix; // /< View of original matrix.
505513 OperandPreparationConfig prepConfig; // /< Configuration for operand preparation.
506514
507515 std::vector<splitint_t > memory; // /< Memory to store the split slices.
@@ -644,7 +652,7 @@ void computeNormalisationVectors(preparedOperand<splitint_t, fp_t>& operand) {
644652 // NOTE 1: This is not the technique used in uoi24.
645653 // NOTE 2: I use exponents instead of powers of 2, as I need the former
646654 // to shift correctly.
647- operand.scalingExponents [outer] = getStoredFloatingPointExponent (operand.powersVector [outer]);
655+ operand.scalingExponents [outer] = fp:: getStoredFloatingPointExponent (operand.powersVector [outer]);
648656 operand.powersVector [outer] = std::ldexp (1.0 , operand.scalingExponents [outer]);
649657 }
650658}
@@ -656,18 +664,21 @@ void computeNormalisationVectors(preparedOperand<splitint_t, fp_t>& operand) {
656664 * matrix, which is used in the splitting algorithms. It extracts the significand
657665 * and sign of each element in the row/column, and stores them in the provided vectors.
658666 *
667+ * The `fraction` and `sign` vectors must be pre-sized to `operand.innerDimension()`
668+ * before calling this function.
669+ *
659670 * @tparam splitint_t Type used to store the integer slices.
660671 * @tparam fp_t Floating-point type of the matrix elements.
661672 * @param fraction Vector to store the fixed-point representation of the elements.
662673 * @param sign Vector to store the signs of the elements.
663674 * @param i The index of the row/column for which to compute the fixed-point representation.
664675 */
665676template <typename splitint_t , typename fp_t >
666- void computeFixedPointRepresentationVector (std::vector<typename FloatingPointTraits<fp_t >::StorageType> &fraction,
677+ void computeFixedPointRepresentationVector (std::vector<typename fp:: FloatingPointTraits<fp_t >::StorageType> &fraction,
667678 std::vector<bool > &sign, size_t outer,
668679 const preparedOperand<splitint_t , fp_t >& operand) {
669- using uint_t = typename FloatingPointTraits<fp_t >::StorageType;
670- constexpr size_t numSignificandBits = FloatingPointTraits<fp_t >::numSignificandBits;
680+ using uint_t = typename fp:: FloatingPointTraits<fp_t >::StorageType;
681+ constexpr size_t numSignificandBits = fp:: FloatingPointTraits<fp_t >::numSignificandBits;
671682 for (size_t inner = 0 ; inner < operand.innerDimension (); inner++) {
672683 fp_t value = operand.operand (outer, inner);
673684 fraction[inner] = std::bit_cast<uint_t >(value);
@@ -696,10 +707,10 @@ void computeFixedPointRepresentationVector(std::vector<typename FloatingPointTra
696707 */
697708template <typename splitint_t , typename fp_t >
698709void computeSplitsWithTruncation (preparedOperand<splitint_t , fp_t >& operand) {
699- using uint_t = typename FloatingPointTraits<fp_t >::StorageType;
710+ using uint_t = typename fp:: FloatingPointTraits<fp_t >::StorageType;
700711
701712 // Compute splits one row/column at a time.
702- constexpr size_t numSignificandBits = FloatingPointTraits<fp_t >::numSignificandBits;
713+ constexpr size_t numSignificandBits = fp:: FloatingPointTraits<fp_t >::numSignificandBits;
703714 auto bitsPerSlice = operand.prepConfig .bitsPerSlice ;
704715 std::vector<uint_t > fraction (operand.innerDimension ());
705716 std::vector<bool > sign (operand.innerDimension ());
@@ -714,7 +725,7 @@ void computeSplitsWithTruncation(preparedOperand<splitint_t, fp_t>& operand) {
714725 for (size_t inner = 0 ; inner < operand.innerDimension (); inner++) {
715726 // NOTE: I could have a special path for 0.
716727 int16_t shiftCounter = numSignificandBits - bitsPerSlice;
717- int currentExponent = getStoredFloatingPointExponent (operand.operand (outer, inner));
728+ int currentExponent = fp:: getStoredFloatingPointExponent (operand.operand (outer, inner));
718729 int16_t exponentDifference = operand.scalingExponents [outer] - currentExponent;
719730 for (size_t slice = 0 ; slice < operand.prepConfig .numSplits ; slice++) {
720731 if (exponentDifference > (signed )bitsPerSlice) {
@@ -755,11 +766,11 @@ void computeSplitsWithTruncation(preparedOperand<splitint_t, fp_t>& operand) {
755766 */
756767template <typename splitint_t , typename fp_t >
757768void computeSplitsWithUnsignedEncoding (preparedOperand<splitint_t , fp_t >& operand) {
758- using uint_t = typename FloatingPointTraits<fp_t >::StorageType;
769+ using uint_t = typename fp:: FloatingPointTraits<fp_t >::StorageType;
759770 using wideint_t = std::conditional_t <(sizeof (splitint_t ) < sizeof (int )), int , std::intmax_t >;
760771
761772 // Compute splits one row/column at a time.
762- constexpr size_t numSignificandBits = FloatingPointTraits<fp_t >::numSignificandBits;
773+ constexpr size_t numSignificandBits = fp:: FloatingPointTraits<fp_t >::numSignificandBits;
763774 auto bitsPerSlice = operand.prepConfig .bitsPerSlice ;
764775 std::vector<uint_t > fraction (operand.innerDimension ());
765776 std::vector<bool > sign (operand.innerDimension ());
@@ -786,7 +797,7 @@ void computeSplitsWithUnsignedEncoding(preparedOperand<splitint_t, fp_t>& operan
786797
787798 // NOTE: I could have a special path for 0.
788799 int16_t shiftCounter;
789- int currentExponent = getStoredFloatingPointExponent (operand.operand (outer, inner));
800+ int currentExponent = fp:: getStoredFloatingPointExponent (operand.operand (outer, inner));
790801 int16_t exponentDifference = operand.scalingExponents [outer] - currentExponent;
791802
792803 splitint_t value = 0 ;
@@ -914,7 +925,7 @@ void computeSplitsWithRoundToNearest(preparedOperand<splitint_t, fp_t>& operand)
914925 for (size_t outer = 0 ; outer < operand.outerDimension (); outer++) {
915926 // Compute exponent in signed arithmetic to avoid wraparound when
916927 // bitsPerSlice * (slice + 1) approaches numSignificandBits.
917- int exponent = static_cast <int >(FloatingPointTraits<fp_t >::numSignificandBits) - static_cast <int >(bitsPerSlice * (slice + 1 )) + 1 ;
928+ int exponent = static_cast <int >(fp:: FloatingPointTraits<fp_t >::numSignificandBits) - static_cast <int >(bitsPerSlice * (slice + 1 )) + 1 ;
918929 fp_t sigma = std::ldexp (0.75 , exponent) * operand.powersVector [outer];
919930 for (size_t inner = 0 ; inner < operand.innerDimension (); inner++) {
920931 auto matrixIndex = operand.operandIndex (outer, inner);
@@ -934,7 +945,7 @@ void computeSplitsWithRoundToNearest(preparedOperand<splitint_t, fp_t>& operand)
934945 * @tparam fp_t Floating-point type of the matrix elements.
935946 */
936947template <typename splitint_t , typename fp_t >
937- preparedOperand<splitint_t , fp_t > prepareOperand (MatrixView<const fp_t > matrix,
948+ preparedOperand<splitint_t , fp_t > prepareOperand (matrix:: MatrixView<const fp_t > matrix,
938949 const OperandPreparationConfig& prepConfig) {
939950 preparedOperand<splitint_t , fp_t > operand;
940951 operand.matrix = matrix;
@@ -1032,6 +1043,7 @@ inline multiplicationSchedule makeSchedule(const config& config) {
10321043
10331044 return schedule;
10341045}
1046+
10351047/* *
10361048 * @brief Compute the exact integer GEMM (General Matrix-Matrix Multiplication).
10371049 *
@@ -1048,11 +1060,11 @@ template <typename splitint_t, typename accumulator_t, typename fp_t>
10481060void computeExactIntegerGEMM (const preparedOperand<splitint_t , fp_t > &A,
10491061 const preparedOperand<splitint_t , fp_t > &B,
10501062 std::vector<accumulator_t > &C,
1051- const matrixLayout layoutC,
1063+ const matrix:: matrixLayout layoutC,
10521064 size_t iBlock, size_t jBlock) {
10531065 for (size_t row = 0 ; row < A.rows (); row++) {
10541066 for (size_t col = 0 ; col < B.cols (); col++) {
1055- auto index = (layoutC == matrixLayout::columnMajor) ? (row + col * A.rows ()) : (col + row * B.cols ());
1067+ auto index = (layoutC == matrix:: matrixLayout::columnMajor) ? (row + col * A.rows ()) : (col + row * B.cols ());
10561068 for (size_t ell = 0 ; ell < A.innerDimension (); ell++) {
10571069 C[index] += A.splitValue (row, ell, iBlock) * B.splitValue (col, ell, jBlock);
10581070 }
@@ -1084,7 +1096,7 @@ template <typename splitint_t, typename accumulator_t, typename fp_t>
10841096std::vector<fp_t > computeProductsWithFloatingPointAccumulation (const preparedOperand<splitint_t , fp_t > &A,
10851097 const preparedOperand<splitint_t , fp_t > &B,
10861098 const multiplicationSchedule &schedule,
1087- const matrixLayout layoutC) {
1099+ const matrix:: matrixLayout layoutC) {
10881100 auto numSplitsA = A.prepConfig .numSplits ;
10891101 auto numSplitsB = B.prepConfig .numSplits ;
10901102 std::vector<fp_t > C (A.rows () * B.cols (), 0.0 );
@@ -1098,7 +1110,7 @@ std::vector<fp_t> computeProductsWithFloatingPointAccumulation(const preparedOpe
10981110 computeExactIntegerGEMM<splitint_t , accumulator_t , fp_t >(A, B, accumulator, layoutC, Aindex, Bindex);
10991111 for (size_t row = 0 ; row < A.rows (); row++) {
11001112 for (size_t col = 0 ; col < B.cols (); col++) {
1101- auto index = (layoutC == matrixLayout::columnMajor) ? (row + col * A.rows ()) : (col + row * B.cols ());
1113+ auto index = (layoutC == matrix:: matrixLayout::columnMajor) ? (row + col * A.rows ()) : (col + row * B.cols ());
11021114 fp_t scaledSum = std::ldexp (static_cast <fp_t >(accumulator[index]), -totalShift);
11031115 fp_t scalingFactor = A.powersVector [row] * B.powersVector [col];
11041116 C[index] += scaledSum * scalingFactor;
@@ -1137,7 +1149,7 @@ template <typename splitint_t, typename accumulator_t, typename fp_t>
11371149std::vector<fp_t > computeProductsWithIntegerAccumulation (const preparedOperand<splitint_t , fp_t > &A,
11381150 const preparedOperand<splitint_t , fp_t > &B,
11391151 const multiplicationSchedule &schedule,
1140- const matrixLayout layoutC) {
1152+ const matrix:: matrixLayout layoutC) {
11411153 auto numSplitsA = A.prepConfig .numSplits ;
11421154 auto numSplitsB = B.prepConfig .numSplits ;
11431155
@@ -1160,7 +1172,7 @@ std::vector<fp_t> computeProductsWithIntegerAccumulation(const preparedOperand<s
11601172 // Scale the accumulated products and accumulate in floating-point arithmetic across diagonals.
11611173 for (size_t row = 0 ; row < A.rows (); row++) {
11621174 for (size_t col = 0 ; col < B.cols (); col++) {
1163- auto index = (layoutC == matrixLayout::columnMajor) ? (row + col * A.rows ()) : (col + row * B.cols ());
1175+ auto index = (layoutC == matrix:: matrixLayout::columnMajor) ? (row + col * A.rows ()) : (col + row * B.cols ());
11641176 fp_t scaledSum = std::ldexp (static_cast <fp_t >(accumulator[index]), -totalShift);
11651177 fp_t scalingFactor = A.powersVector [row] * B.powersVector [col];
11661178 C[index] += scaledSum * scalingFactor;
@@ -1191,15 +1203,15 @@ std::vector<fp_t> computeProductsWithIntegerAccumulation(const preparedOperand<s
11911203 * @return Resulting matrix product.
11921204 */
11931205template <typename fp_t , typename splitint_t , typename accumulator_t >
1194- std::vector<fp_t > gemmi (const std::vector<fp_t > &A, const matrixLayout layoutA,
1195- const std::vector<fp_t > &B, const matrixLayout layoutB,
1206+ std::vector<fp_t > gemmi (const std::vector<fp_t > &A, const matrix:: matrixLayout layoutA,
1207+ const std::vector<fp_t > &B, const matrix:: matrixLayout layoutB,
11961208 const size_t m, const size_t k, const size_t n,
1197- const matrixLayout layoutC,
1209+ const matrix:: matrixLayout layoutC,
11981210 const multiterm::config &config) {
11991211
12001212 // Build matrix views.
1201- auto viewA = makeMatrixView (A, m, k, layoutA);
1202- auto viewB = makeMatrixView (B, k, n, layoutB);
1213+ auto viewA = matrix:: makeMatrixView (A, m, k, layoutA);
1214+ auto viewB = matrix:: makeMatrixView (B, k, n, layoutB);
12031215
12041216 // Validate inputs and derive execution parameters.
12051217 auto derivedParameters = multiterm::deriveParameters<fp_t , splitint_t , accumulator_t >(viewA, viewB, config);
@@ -1226,11 +1238,11 @@ std::vector<fp_t> gemmi (const std::vector<fp_t> &A, const matrixLayout layoutA,
12261238}
12271239
12281240template <typename fp_t , typename splitint_t , typename accumulator_t >
1229- std::vector<fp_t > gemmi (const std::vector<fp_t > &A, const matrixLayout layoutA,
1230- const std::vector<fp_t > &B, const matrixLayout layoutB,
1241+ std::vector<fp_t > gemmi (const std::vector<fp_t > &A, const matrix:: matrixLayout layoutA,
1242+ const std::vector<fp_t > &B, const matrix:: matrixLayout layoutB,
12311243 const size_t m, const size_t k, const size_t n, const size_t numSplits) {
12321244 return gemmi <fp_t , splitint_t , accumulator_t > (A, layoutA, B, layoutB, m, k, n,
1233- matrixLayout::columnMajor,
1245+ matrix:: matrixLayout::columnMajor,
12341246 multiterm::config{numSplits, numSplits,
12351247 multiterm::splittingStrategy::roundToNearest,
12361248 multiterm::multiplicationStrategy::reduced,
0 commit comments