Mercurial > octave-nkf
comparison scripts/sparse/private/__sprand__.m @ 20434:26bd6008fc9c
maint: Rename __sprand_impl__.m to __sprand__.m
* scripts/sparse/private/__sprand__.m: Renamed file.
* scripts/sparse/private/__sprand_impl__.m: Removed file.
* scripts/sparse/module.mk: Rename file in build system.
* sprand.m, sprandn.m: Rename file in calling functions.
author | Rik <rik@octave.org> |
---|---|
date | Sun, 26 Jul 2015 08:50:04 -0700 |
parents | scripts/sparse/private/__sprand_impl__.m@83792dd9bcc1 |
children |
comparison
equal
deleted
inserted
replaced
20432:1bc95d7148b7 | 20434:26bd6008fc9c |
---|---|
1 ## Copyright (C) 2004-2015 Paul Kienzle | |
2 ## Copyright (C) 2012 Jordi GutiƩrrez Hermoso | |
3 ## | |
4 ## This file is part of Octave. | |
5 ## | |
6 ## Octave is free software; you can redistribute it and/or modify it | |
7 ## under the terms of the GNU General Public License as published by | |
8 ## the Free Software Foundation; either version 3 of the License, or (at | |
9 ## your option) any later version. | |
10 ## | |
11 ## Octave is distributed in the hope that it will be useful, but | |
12 ## WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
14 ## General Public License for more details. | |
15 ## | |
16 ## You should have received a copy of the GNU General Public License | |
17 ## along with Octave; see the file COPYING. If not, see | |
18 ## <http://www.gnu.org/licenses/>. | |
19 ## | |
20 ## Original version by Paul Kienzle distributed as free software in the | |
21 ## public domain. | |
22 | |
23 ## -*- texinfo -*- | |
24 ## @deftypefn {Function File} {} __sprand__ (@var{s}, @var{randfun}) | |
25 ## @deftypefnx {Function File} {} __sprand__ (@var{m}, @var{n}, @var{d}, @var{fcnname}, @var{randfun}) | |
26 ## @deftypefnx {Function File} {} __sprand__ (@var{m}, @var{n}, @var{d}, @var{rc}, @var{fcnname}, @var{randfun}) | |
27 ## Undocumented internal function. | |
28 ## @end deftypefn | |
29 | |
30 ## Actual implementation of sprand and sprandn happens here. | |
31 | |
32 function S = __sprand__ (varargin) | |
33 | |
34 if (nargin == 2) | |
35 [m, randfun] = deal (varargin{1:2}); | |
36 [i, j] = find (m); | |
37 [nr, nc] = size (m); | |
38 S = sparse (i, j, randfun (size (i)), nr, nc); | |
39 else | |
40 if (nargin == 5) | |
41 [m, n, d, fcnname, randfun] = deal (varargin{:}); | |
42 else | |
43 [m, n, d, rc, fcnname, randfun] = deal (varargin{:}); | |
44 endif | |
45 | |
46 if (! (isscalar (m) && m == fix (m) && m > 0)) | |
47 error ("%s: M must be an integer greater than 0", fcnname); | |
48 endif | |
49 if (! (isscalar (n) && n == fix (n) && n > 0)) | |
50 error ("%s: N must be an integer greater than 0", fcnname); | |
51 endif | |
52 if (d < 0 || d > 1) | |
53 error ("%s: density D must be between 0 and 1", fcnname); | |
54 endif | |
55 | |
56 if (nargin == 5) | |
57 mn = m*n; | |
58 k = round (d*mn); | |
59 if (mn > sizemax ()) | |
60 ## randperm will overflow, so use alternative methods | |
61 | |
62 idx = unique (fix (rand (1.01*k, 1) * mn)) + 1; | |
63 | |
64 ## idx contains random numbers in [1,mn] | |
65 ## Generate 1% more random values than necessary in order to reduce the | |
66 ## probability that there are less than k distinct values; maybe a | |
67 ## better strategy could be used but I don't think it's worth the price. | |
68 | |
69 ## actual number of entries in S | |
70 k = min (length (idx), k); | |
71 j = floor ((idx(1:k) - 1) / m); | |
72 i = idx(1:k) - j * m; | |
73 j++; | |
74 else | |
75 idx = randperm (mn, k); | |
76 [i, j] = ind2sub ([m, n], idx); | |
77 endif | |
78 | |
79 S = sparse (i, j, randfun (k, 1), m, n); | |
80 | |
81 elseif (nargin == 6) | |
82 ## Create a matrix with specified reciprocal condition number. | |
83 | |
84 if (! isscalar (rc) && ! isvector (rc)) | |
85 error ("%s: RC must be a scalar or vector", fcnname); | |
86 endif | |
87 | |
88 ## We want to reverse singular valued decomposition A=U*S*V'. | |
89 ## First, first S is constructed and then U = U1*U2*..Un and | |
90 ## V' = V1*V2*..Vn are seen as Jacobi rotation matrices with angles and | |
91 ## planes of rotation randomized. Repeatedly apply rotations until the | |
92 ## required density for A is achieved. | |
93 | |
94 if (isscalar (rc)) | |
95 if (rc < 0 || rc > 1) | |
96 error ("%s: reciprocal condition number RC must be between 0 and 1", fcnname); | |
97 endif | |
98 ## Reciprocal condition number is ratio of smallest SV to largest SV | |
99 ## Generate singular values randomly and sort them to build S | |
100 ## Random singular values in range [rc, 1]. | |
101 v = rand (1, min (m,n)) * (1 - rc) + rc; | |
102 v(1) = 1; | |
103 v(end) = rc; | |
104 v = sort (v, "descend"); | |
105 S = sparse (diag (v, m, n)); | |
106 else | |
107 ## Only the min (m, n) greater singular values from rc vector are used. | |
108 if (length (rc) > min (m,n)) | |
109 rc = rc(1:min(m, n)); | |
110 endif | |
111 S = sparse (diag (sort (rc, "descend"), m, n)); | |
112 endif | |
113 | |
114 Uinit = speye (m); | |
115 Vinit = speye (n); | |
116 k = round (d*m*n); | |
117 while (nnz (S) < k) | |
118 if (m > 1) | |
119 ## Construct U randomized rotation matrix | |
120 rot_angleu = 2 * pi * rand (); | |
121 cu = cos (rot_angleu); su = sin (rot_angleu); | |
122 rndtmp = randperm (m, 2); | |
123 i = rndtmp(1); j = rndtmp(2); | |
124 U = Uinit; | |
125 U(i, i) = cu; U(i, j) = -su; | |
126 U(j, i) = su; U(j, j) = cu; | |
127 S = U * S; | |
128 endif | |
129 if (n > 1) | |
130 ## Construct V' randomized rotation matrix | |
131 rot_anglev = 2 * pi * rand (); | |
132 cv = cos (rot_anglev); sv = sin (rot_anglev); | |
133 rndtmp = randperm (n, 2); | |
134 i = rndtmp(1); j = rndtmp(2); | |
135 V = Vinit; | |
136 V(i, i) = cv; V(i, j) = sv; | |
137 V(j, i) = -sv; V(j, j) = cv; | |
138 S *= V; | |
139 endif | |
140 endwhile | |
141 endif | |
142 endif | |
143 | |
144 endfunction | |
145 |