function imul( 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 16-bits:
	ha = ( a>>>16 )>>>0; // asm type annotation
	hb = ( b>>>16 )>>>0; // asm type annotation

	// Isolate the least significant 16-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))<<16 )>>>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 )|0; // asm type annotation
}
Performs C-like multiplication of two signed 32-bit integers.

## Method

-   To emulate C-like multiplication without the aid of 64-bit integers, we recognize that a 32-bit integer can be split into two 16-bit words

    ```tex
    a = w_h*2^{16} + w_l
    ```

    where \\( w_h \\) is the most significant 16 bits and \\( w_l \\) is the least significant 16 bits. For example, consider the maximum signed 32-bit integer \\( 2^{31}-1 \\)

    ```binarystring
    01111111111111111111111111111111
    ```

    The 16-bit high word is then

    ```binarystring
    0111111111111111
    ```

    and the 16-bit low word

    ```binarystring
    1111111111111111
    ```

    If we cast the high word to 32-bit precision and multiply by \\( 2^{16} \\) (equivalent to a 16-bit left shift), then the bit sequence is

    ```binarystring
    01111111111111110000000000000000
    ```

    Similarly, upon casting the low word to 32-bit precision, the bit sequence is

    ```binarystring
    00000000000000001111111111111111
    ```

    From the rules of binary addition, we recognize that adding the two 32-bit values for the high and low words will return our original value \\( 2^{31}-1 \\).

-   Accordingly, the multiplication of two 32-bit integers can be expressed

    ```tex
    \begin{align*}
    a \cdot b &= ( a_h \cdot 2^{16} + a_l) \cdot ( b_h \cdot 2^{16} + b_l) \\
          &= a_l \cdot b_l + a_h \cdot b_l \cdot 2^{16} + a_l \cdot b_h \cdot 2^{16} + (a_h \cdot b_h) \cdot 2^{32} \\
          &= a_l \cdot b_l + (a_h \cdot b_l + a_l \cdot b_h) \cdot 2^{16} + (a_h \cdot b_h) \cdot 2^{32}
    \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 32-bit integer, the return value will be modulo \\( 2^{32} \\). Stated another way, we only care about the low word of a 64-bit result.

-   Accordingly, the last term, being evenly divisible by \\( 2^{32} \\), 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) << 16
    ```

-   Lastly, the second term in the above equation contributes to the middle bits and may cause the product to "overflow". However, we can disregard (`>>>0`) overflow bits due to modulo arithmetic, as discussed earlier with regard to the term involving the partial product of high words.

@param {integer32} a - integer
@param {integer32} b - integer
@returns {integer32} product

@example
var v = imul( -10|0, 4|0 );
// returns -40