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

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177

178

179

180

181

182

183

184

185

186

187

from __future__ import division, print_function, absolute_import 

 

import numpy as np 

from numpy.linalg import LinAlgError 

from .blas import get_blas_funcs 

from .lapack import get_lapack_funcs 

 

__all__ = ['LinAlgError', 'LinAlgWarning', 'norm'] 

 

 

class LinAlgWarning(RuntimeWarning): 

""" 

The warning emitted when a linear algebra related operation is close 

to fail conditions of the algorithm or loss of accuracy is expected. 

""" 

pass 

 

 

def norm(a, ord=None, axis=None, keepdims=False): 

""" 

Matrix or vector norm. 

 

This function is able to return one of seven different matrix norms, 

or one of an infinite number of vector norms (described below), depending 

on the value of the ``ord`` parameter. 

 

Parameters 

---------- 

a : (M,) or (M, N) array_like 

Input array. If `axis` is None, `a` must be 1-D or 2-D. 

ord : {non-zero int, inf, -inf, 'fro'}, optional 

Order of the norm (see table under ``Notes``). inf means numpy's 

`inf` object 

axis : {int, 2-tuple of ints, None}, optional 

If `axis` is an integer, it specifies the axis of `a` along which to 

compute the vector norms. If `axis` is a 2-tuple, it specifies the 

axes that hold 2-D matrices, and the matrix norms of these matrices 

are computed. If `axis` is None then either a vector norm (when `a` 

is 1-D) or a matrix norm (when `a` is 2-D) is returned. 

keepdims : bool, optional 

If this is set to True, the axes which are normed over are left in the 

result as dimensions with size one. With this option the result will 

broadcast correctly against the original `a`. 

 

Returns 

------- 

n : float or ndarray 

Norm of the matrix or vector(s). 

 

Notes 

----- 

For values of ``ord <= 0``, the result is, strictly speaking, not a 

mathematical 'norm', but it may still be useful for various numerical 

purposes. 

 

The following norms can be calculated: 

 

===== ============================ ========================== 

ord norm for matrices norm for vectors 

===== ============================ ========================== 

None Frobenius norm 2-norm 

'fro' Frobenius norm -- 

inf max(sum(abs(x), axis=1)) max(abs(x)) 

-inf min(sum(abs(x), axis=1)) min(abs(x)) 

0 -- sum(x != 0) 

1 max(sum(abs(x), axis=0)) as below 

-1 min(sum(abs(x), axis=0)) as below 

2 2-norm (largest sing. value) as below 

-2 smallest singular value as below 

other -- sum(abs(x)**ord)**(1./ord) 

===== ============================ ========================== 

 

The Frobenius norm is given by [1]_: 

 

:math:`||A||_F = [\\sum_{i,j} abs(a_{i,j})^2]^{1/2}` 

 

The ``axis`` and ``keepdims`` arguments are passed directly to 

``numpy.linalg.norm`` and are only usable if they are supported 

by the version of numpy in use. 

 

References 

---------- 

.. [1] G. H. Golub and C. F. Van Loan, *Matrix Computations*, 

Baltimore, MD, Johns Hopkins University Press, 1985, pg. 15 

 

Examples 

-------- 

>>> from scipy.linalg import norm 

>>> a = np.arange(9) - 4.0 

>>> a 

array([-4., -3., -2., -1., 0., 1., 2., 3., 4.]) 

>>> b = a.reshape((3, 3)) 

>>> b 

array([[-4., -3., -2.], 

[-1., 0., 1.], 

[ 2., 3., 4.]]) 

 

>>> norm(a) 

7.745966692414834 

>>> norm(b) 

7.745966692414834 

>>> norm(b, 'fro') 

7.745966692414834 

>>> norm(a, np.inf) 

4 

>>> norm(b, np.inf) 

9 

>>> norm(a, -np.inf) 

0 

>>> norm(b, -np.inf) 

2 

 

>>> norm(a, 1) 

20 

>>> norm(b, 1) 

7 

>>> norm(a, -1) 

-4.6566128774142013e-010 

>>> norm(b, -1) 

6 

>>> norm(a, 2) 

7.745966692414834 

>>> norm(b, 2) 

7.3484692283495345 

 

>>> norm(a, -2) 

0 

>>> norm(b, -2) 

1.8570331885190563e-016 

>>> norm(a, 3) 

5.8480354764257312 

>>> norm(a, -3) 

0 

 

""" 

# Differs from numpy only in non-finite handling and the use of blas. 

a = np.asarray_chkfinite(a) 

 

# Only use optimized norms if axis and keepdims are not specified. 

if a.dtype.char in 'fdFD' and axis is None and not keepdims: 

 

if ord in (None, 2) and (a.ndim == 1): 

# use blas for fast and stable euclidean norm 

nrm2 = get_blas_funcs('nrm2', dtype=a.dtype) 

return nrm2(a) 

 

if a.ndim == 2 and axis is None and not keepdims: 

# Use lapack for a couple fast matrix norms. 

# For some reason the *lange frobenius norm is slow. 

lange_args = None 

# Make sure this works if the user uses the axis keywords 

# to apply the norm to the transpose. 

if ord == 1: 

if np.isfortran(a): 

lange_args = '1', a 

elif np.isfortran(a.T): 

lange_args = 'i', a.T 

elif ord == np.inf: 

if np.isfortran(a): 

lange_args = 'i', a 

elif np.isfortran(a.T): 

lange_args = '1', a.T 

if lange_args: 

lange = get_lapack_funcs('lange', dtype=a.dtype) 

return lange(*lange_args) 

 

# Filter out the axis and keepdims arguments if they aren't used so they 

# are never inadvertently passed to a version of numpy that doesn't 

# support them. 

if axis is not None: 

if keepdims: 

return np.linalg.norm(a, ord=ord, axis=axis, keepdims=keepdims) 

return np.linalg.norm(a, ord=ord, axis=axis) 

return np.linalg.norm(a, ord=ord) 

 

 

def _datacopied(arr, original): 

""" 

Strict check for `arr` not sharing any data with `original`, 

under the assumption that arr = asarray(original) 

 

""" 

if arr is original: 

return False 

if not isinstance(original, np.ndarray) and hasattr(original, '__array__'): 

return False 

return arr.base is None