Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 | 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 10000x 10000x 10000x 10000x 10000x 10000x 10000x 10000x 10000x 10000x 10000x 10000x 10000x 10000x 10000x 10000x 10000x 10000x 10000x 10000x 10000x 10000x 10000x 10000x 10000x 10000x 2x 2x 2x 2x 2x | /**
* @license Apache-2.0
*
* Copyright (c) 2026 The Stdlib Authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
'use strict';
// VARIABLES //
// Define a mask for the least significant 8 bits (low word): 255 => 0x00ff => 0000000011111111
var LOW_WORD_MASK = 0x00ff; // asm type annotation
// MAIN //
/**
* Performs C-like multiplication of two signed 16-bit integers.
*
* ## Method
*
* - To emulate C-like multiplication without the aid of 64-bit integers, we recognize that a 16-bit integer can be split into two 8-bit bytes
*
* ```tex
* a = w_h*2^{8} + w_l
* ```
*
* where \\( w_h \\) is the most significant 8 bits and \\( w_l \\) is the least significant 8 bits. For example, consider the maximum signed 16-bit integer \\( 2^{15}-1 \\)
*
* ```binarystring
* 0111111111111111
* ```
*
* The 8-bit high word is then
*
* ```binarystring
* 01111111
* ```
*
* and the 8-bit low word
*
* ```binarystring
* 11111111
* ```
*
* If we cast the high word to 16-bit precision and multiply by \\( 2^{8} \\) (equivalent to a 8-bit left shift), then the bit sequence is
*
* ```binarystring
* 0111111100000000
* ```
*
* Similarly, upon casting the low word to 16-bit precision, the bit sequence is
*
* ```binarystring
* 0000000011111111
* ```
*
* From the rules of binary addition, we recognize that adding the two 16-bit values for the high and low words will return our original value \\( 2^{15}-1 \\).
*
* - Accordingly, the multiplication of two 16-bit integers can be expressed
*
* ```tex
* \begin{align*}
* a \cdot b &= ( a_h \cdot 2^{8} + a_l) \cdot ( b_h \cdot 2^{8} + b_l) \\
* &= a_l \cdot b_l + a_h \cdot b_l \cdot 2^{8} + a_l \cdot b_h \cdot 2^{8} + (a_h \cdot b_h) \cdot 2^{16} \\
* &= a_l \cdot b_l + (a_h \cdot b_l + a_l \cdot b_h) \cdot 2^{8} + (a_h \cdot b_h) \cdot 2^{16}
* \end{align*}
* ```
*
* - We note that multiplying (dividing) an integer by \\( 2^n \\) is equivalent to performing a left (right) shift of \\( n \\) bits.
*
* - Further, as we want to return an integer of the same precision, for a 16-bit integer, the return value will be modulo \\( 2^{16} \\). Stated another way, we only care about the low word of a 32-bit result.
*
* - Accordingly, the last term, being evenly divisible by \\( 2^{16} \\), drops from the equation leaving the remaining two terms as the remainder.
*
* ```tex
* a \cdot b = a_l \cdot b_l + (a_h \cdot b_l + a_l \cdot b_h) << 8
* ```
*
* - Lastly, the second term in the above equation contributes to the middle bits and may cause the product to "overflow". However, we can disregard overflow bits due to modulo arithmetic, as discussed earlier with regard to the term involving the partial product of high bytes.
*
* @param {integer16} a - integer
* @param {integer16} b - integer
* @returns {integer16} product
*
* @example
* var v = mul( -10, 4 );
* // returns -40
*/
function mul( a, b ) {
var lbits;
var mbits;
var ha;
var hb;
var la;
var lb;
a |= 0; // asm type annotation
b |= 0; // asm type annotation
// Isolate the most significant 8-bits:
ha = ( a << 16 ) >> 24; // asm type annotation
hb = ( b << 16 ) >> 24; // asm type annotation
// Isolate the least significant 8 bits:
la = ( a & LOW_WORD_MASK )>>>0; // asm type annotation
lb = ( b & LOW_WORD_MASK )>>>0; // asm type annotation
// Shift by zero (`>>>0`) sets the sign on the high part of the low word (i.e., "mid-bits"):
lbits = ( la*lb )>>>0; // asm type annotation; no integer overflow possible
mbits = ( ((ha*lb) + (la*hb))<<8 )>>>0; // asm type annotation; possible integer overflow
// The final `|0` converts from an "unsigned integer" (possible integer overflow during sum) to a signed integer:
return ( ( (lbits + mbits) & 0xFFFF ) ^ 0x8000 ) - 0x8000; // asm type annotation
}
// EXPORTS //
module.exports = mul;
|