* Returns the matrix norm or vector norm of a given tensor. * @param {number|string} [p='fro'] The order of norm * @param {number|null} [dim=null] Specifies which dimension of the tensor to calculate the norm across. * If dim is None, the norm will be calculated across all dimensions
(p = 'fro', dim = null, keepdim = false)
| 498 | * @returns {Tensor} The norm of the tensor. |
| 499 | */ |
| 500 | norm(p = 'fro', dim = null, keepdim = false) { |
| 501 | if (p === 'fro') { |
| 502 | // NOTE: Since we only support integer dims, Frobenius norm produces the same result as p=2. |
| 503 | p = 2; |
| 504 | } else if (typeof p === 'string') { |
| 505 | throw Error(`Unsupported norm: ${p}`); |
| 506 | } |
| 507 | |
| 508 | const this_data = this.data; |
| 509 | const is_bigint = this_data instanceof BigInt64Array || this_data instanceof BigUint64Array; |
| 510 | |
| 511 | if (is_bigint && p !== 1) { |
| 512 | throw Error(`Expected a floating point tensor as input. Got ${this.type}`); |
| 513 | } |
| 514 | |
| 515 | let fn, zero; |
| 516 | if (is_bigint) { |
| 517 | fn = (/** @type {bigint} */ a, /** @type {bigint} */ b) => a + b; |
| 518 | zero = 0n; |
| 519 | } else { |
| 520 | fn = (/** @type {number} */ a, /** @type {number} */ b) => a + b ** p; |
| 521 | zero = 0; |
| 522 | } |
| 523 | |
| 524 | if (dim === null) { |
| 525 | // @ts-ignore |
| 526 | let val = this_data.reduce(fn, zero); |
| 527 | if (p !== 1) { |
| 528 | val = val ** (1 / p); |
| 529 | } |
| 530 | return new Tensor(this.type, [val], []); |
| 531 | } |
| 532 | |
| 533 | const [type, result, resultDims] = reduce_helper(fn, this, dim, keepdim); |
| 534 | |
| 535 | if (p !== 1) { |
| 536 | for (let i = 0; i < result.length; ++i) { |
| 537 | result[i] = result[i] ** (1 / p); |
| 538 | } |
| 539 | } |
| 540 | return new Tensor(type, result, resultDims); |
| 541 | } |
| 542 | |
| 543 | /** |
| 544 | * Performs `L_p` normalization of inputs over specified dimension. Operates in place. |
no test coverage detected