13
13
# limitations under the License.
14
14
15
15
import math
16
- import os
16
+ from pathlib import Path
17
17
from typing import Optional
18
18
19
19
import torch
20
20
from safetensors import safe_open
21
21
22
22
23
- REPO_PATH = os . path . join ( os . path . dirname ( __file__ ), "hadamards.safetensors" )
23
+ REPO_PATH = Path ( __file__ ). parent / "hadamards.safetensors"
24
24
25
25
26
26
__all__ = ["random_hadamard_matrix" , "deterministic_hadamard_matrix" , "is_pow2" ]
@@ -42,6 +42,8 @@ def deterministic_hadamard_matrix(
42
42
Adapated from https://github.com/scipy/scipy/blob/v1.15.2/scipy/linalg/_special_matrices.py # noqa: E501
43
43
44
44
:param size: order of the matrix, must be a power of 2
45
+ :param dtype: data type of matrix
46
+ :param device: device to construct matrix on
45
47
:return: hadamard matrix of size `size`
46
48
"""
47
49
if size <= 0 :
@@ -54,7 +56,7 @@ def deterministic_hadamard_matrix(
54
56
H = torch .tensor ([[1 ]], dtype = dtype , device = device )
55
57
56
58
# Sylvester's construction
57
- for _ in range (0 , log2 ):
59
+ for _ in range (log2 ):
58
60
H = torch .vstack ((torch .hstack ((H , H )), torch .hstack ((H , - H ))))
59
61
60
62
return H / math .sqrt (size )
@@ -78,6 +80,8 @@ def random_hadamard_matrix(
78
80
Known matrices were retrieved from N. J. A. Sloane's Library of Hadamard Matrices http://www.neilsloane.com/hadamard/ # noqa: E501
79
81
80
82
:param size: The dimension of the hamadard matrix
83
+ :param dtype: data type of matrix
84
+ :param device: device to construct matrix on
81
85
:param gen: Optional generator random values
82
86
:return: randomly generated hadamard matrix
83
87
"""
@@ -89,10 +93,16 @@ def random_hadamard_matrix(
89
93
90
94
91
95
def is_pow2 (n : int ) -> bool :
92
- return (n & (n - 1 ) == 0 ) and (n > 0 )
96
+ """
97
+ Check if a number is a power of 2
98
+
99
+ :param n: number to check
100
+ :return: True iff `n` is a power of 2
101
+ """
102
+ return n > 0 and (n & (n - 1 ) == 0 )
93
103
94
104
95
- def _get_known_divisor (
105
+ def _fetch_hadamard_divisor (
96
106
n : int ,
97
107
dtype : torch .dtype ,
98
108
device : torch .device = torch .device ("cpu" ),
@@ -111,7 +121,7 @@ def _get_known_divisor(
111
121
:return: a known hadamard matrix of size `n` if one exists, else None
112
122
"""
113
123
with safe_open (file_path , framework = "pt" , device = str (device )) as file :
114
- divisors = sorted ([ int (key ) for key in file .keys ()] , reverse = True )
124
+ divisors = sorted (( int (key ) for key in file .keys ()) , reverse = True )
115
125
for divisor in divisors :
116
126
if n % divisor == 0 and is_pow2 (n // divisor ):
117
127
return file .get_tensor (str (divisor )).to (dtype = dtype )
@@ -125,7 +135,7 @@ def _matmul_hadU(X: torch.Tensor) -> torch.Tensor:
125
135
device = X .device
126
136
127
137
# Check if we have the determined hadamard matrix
128
- hadK = _get_known_divisor (size , dtype , device = device )
138
+ hadK = _fetch_hadamard_divisor (size , dtype , device = device )
129
139
if hadK is None :
130
140
raise ValueError (f"Cannot construct random hadamard matrix of size { size } " )
131
141
K = hadK .size (0 )
0 commit comments