unary.py 42 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233
  1. # Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.
  2. #
  3. # Licensed under the Apache License, Version 2.0 (the "License");
  4. # you may not use this file except in compliance with the License.
  5. # You may obtain a copy of the License at
  6. #
  7. # http://www.apache.org/licenses/LICENSE-2.0
  8. #
  9. # Unless required by applicable law or agreed to in writing, software
  10. # distributed under the License is distributed on an "AS IS" BASIS,
  11. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. # See the License for the specific language governing permissions and
  13. # limitations under the License.
  14. import numpy as np
  15. import paddle
  16. from paddle import _C_ops, in_dynamic_mode
  17. from paddle.base.data_feeder import check_type, check_variable_and_dtype
  18. from paddle.base.framework import convert_np_dtype_to_dtype_, core, dygraph_only
  19. from paddle.common_ops_import import Variable
  20. from paddle.framework import LayerHelper
  21. __all__ = []
  22. _int_dtype_ = [
  23. core.VarDesc.VarType.UINT8,
  24. core.VarDesc.VarType.INT8,
  25. core.VarDesc.VarType.INT16,
  26. core.VarDesc.VarType.INT32,
  27. core.VarDesc.VarType.INT64,
  28. core.VarDesc.VarType.BOOL,
  29. ]
  30. @dygraph_only
  31. def sin(x, name=None):
  32. """
  33. Calculate elementwise sin of SparseTensor, requiring x to be a SparseCooTensor or SparseCsrTensor.
  34. .. math::
  35. out = sin(x)
  36. Parameters:
  37. x (Tensor): The input Sparse Tensor with data type float32, float64.
  38. name (str, optional): Name for the operation (optional, default is None).
  39. For more information, please refer to :ref:`api_guide_Name`.
  40. Returns:
  41. A Sparse Tensor with the same data type and shape as ``x`` .
  42. Examples:
  43. .. code-block:: python
  44. >>> import paddle
  45. >>> dense_x = paddle.to_tensor([-2., 0., 1.])
  46. >>> sparse_x = dense_x.to_sparse_coo(1)
  47. >>> out = paddle.sparse.sin(sparse_x)
  48. >>> out
  49. Tensor(shape=[3], dtype=paddle.float32, place=Place(cpu), stop_gradient=True,
  50. indices=[[0, 2]],
  51. values=[-0.90929741, 0.84147102])
  52. """
  53. return _C_ops.sparse_sin(x)
  54. @dygraph_only
  55. def tan(x, name=None):
  56. """
  57. Calculate elementwise tan of SparseTensor, requiring x to be a SparseCooTensor or SparseCsrTensor.
  58. .. math::
  59. out = tan(x)
  60. Parameters:
  61. x (Tensor): The input Sparse Tensor with data type float32, float64.
  62. name (str, optional): Name for the operation (optional, default is None).
  63. For more information, please refer to :ref:`api_guide_Name`.
  64. Returns:
  65. A Sparse Tensor with the same data type and shape as ``x`` .
  66. Examples:
  67. .. code-block:: python
  68. >>> import paddle
  69. >>> dense_x = paddle.to_tensor([-2., 0., 1.])
  70. >>> sparse_x = dense_x.to_sparse_coo(1)
  71. >>> out = paddle.sparse.tan(sparse_x)
  72. >>> out
  73. Tensor(shape=[3], dtype=paddle.float32, place=Place(cpu), stop_gradient=True,
  74. indices=[[0, 2]],
  75. values=[2.18503976, 1.55740774])
  76. """
  77. return _C_ops.sparse_tan(x)
  78. @dygraph_only
  79. def asin(x, name=None):
  80. """
  81. Calculate elementwise asin of SparseTensor, requiring x to be a SparseCooTensor or SparseCsrTensor.
  82. .. math::
  83. out = asin(x)
  84. Parameters:
  85. x (Tensor): The input Sparse Tensor with data type float32, float64.
  86. name (str, optional): Name for the operation (optional, default is None).
  87. For more information, please refer to :ref:`api_guide_Name`.
  88. Returns:
  89. A Sparse Tensor with the same data type and shape as ``x`` .
  90. Examples:
  91. .. code-block:: python
  92. >>> import paddle
  93. >>> dense_x = paddle.to_tensor([-2., 0., 1.])
  94. >>> sparse_x = dense_x.to_sparse_coo(1)
  95. >>> out = paddle.sparse.asin(sparse_x)
  96. >>> out
  97. Tensor(shape=[3], dtype=paddle.float32, place=Place(cpu), stop_gradient=True,
  98. indices=[[0, 2]],
  99. values=[nan , 1.57079625])
  100. """
  101. return _C_ops.sparse_asin(x)
  102. @dygraph_only
  103. def transpose(x, perm, name=None):
  104. """
  105. Changes the perm order of ``x`` without changing its data, requiring x to be a SparseCooTensor or SparseCsrTensor.
  106. .. math::
  107. out = transpose(x, perm)
  108. Parameters:
  109. x (Tensor): The input Sparse Tensor with data type float32, float64.
  110. perm (list|tuple): Permute the input according to the data of perm.
  111. name (str, optional): Name for the operation (optional, default is None).
  112. For more information, please refer to :ref:`api_guide_Name`.
  113. Returns:
  114. A transposed Sparse Tensor with the same data type as ``x``.
  115. Examples:
  116. .. code-block:: python
  117. >>> import paddle
  118. >>> dense_x = paddle.to_tensor([[-2., 0.], [1., 2.]])
  119. >>> sparse_x = dense_x.to_sparse_coo(1)
  120. >>> out = paddle.sparse.transpose(sparse_x, [1, 0])
  121. >>> out
  122. Tensor(shape=[2, 2], dtype=paddle.float32, place=Place(cpu), stop_gradient=True,
  123. indices=[[0, 0]],
  124. values=[[-2., 0.],
  125. [ 1., 2.]])
  126. """
  127. return _C_ops.sparse_transpose(x, perm)
  128. def sum(x, axis=None, dtype=None, keepdim=False, name=None):
  129. """
  130. Computes the sum of sparse tensor elements over the given dimension, requiring x to be a SparseCooTensor or SparseCsrTensor.
  131. Args:
  132. x (Tensor): An N-D Tensor, the data type is bool, float16, float32, float64, int32 or int64.
  133. axis (int|list|tuple, optional): The dimensions along which the sum is performed. If
  134. :attr:`None`, sum all elements of :attr:`x` and return a
  135. Tensor with a single element, otherwise must be in the
  136. range :math:`[-rank(x), rank(x))`. If :math:`axis[i] < 0`,
  137. the dimension to reduce is :math:`rank + axis[i]`.
  138. dtype (str, optional): The dtype of output Tensor. The default value is None, the dtype
  139. of output is the same as input Tensor `x`.
  140. keepdim (bool, optional): Whether to reserve the reduced dimension in the
  141. output Tensor. The result Tensor will have one fewer dimension
  142. than the :attr:`x` unless :attr:`keepdim` is true, default
  143. value is False.
  144. name (str, optional): Name for the operation (optional, default is None). For more information, please refer to :ref:`api_guide_Name`.
  145. Returns:
  146. Tensor: Results of summation operation on the specified axis of input Tensor `x`.
  147. if `x.dtype='bool'` or `x.dtype='int32'`, it's data type is `'int64'`,
  148. otherwise it's data type is the same as `x`.
  149. Examples:
  150. .. code-block:: python
  151. >>> import paddle
  152. >>> dense_x = paddle.to_tensor([[-2., 0.], [1., 2.]])
  153. >>> sparse_x = dense_x.to_sparse_coo(1)
  154. >>> out1 = paddle.sparse.sum(sparse_x)
  155. >>> out1
  156. Tensor(shape=[1], dtype=paddle.float32, place=Place(cpu), stop_gradient=True,
  157. indices=[0],
  158. values=1.)
  159. >>> out2 = paddle.sparse.sum(sparse_x, axis=0)
  160. >>> out2
  161. Tensor(shape=[1, 2], dtype=paddle.float32, place=Place(cpu), stop_gradient=True,
  162. indices=[[0]],
  163. values=[[-1., 2.]])
  164. >>> out3 = paddle.sparse.sum(sparse_x, axis=-1)
  165. >>> out3
  166. Tensor(shape=[2], dtype=paddle.float32, place=Place(cpu), stop_gradient=True,
  167. indices=[[0, 1]],
  168. values=[-2., 3.])
  169. >>> out4 = paddle.sparse.sum(sparse_x, axis=1, keepdim=True)
  170. >>> out4
  171. Tensor(shape=[2, 1], dtype=paddle.float32, place=Place(cpu), stop_gradient=True,
  172. indices=[[0, 1]],
  173. values=[[-2.],
  174. [ 3.]])
  175. """
  176. dtype_flag = False
  177. if dtype is not None:
  178. dtype_flag = True
  179. dtype = convert_np_dtype_to_dtype_(dtype)
  180. if in_dynamic_mode():
  181. return _C_ops.sparse_sum(x, axis, dtype, keepdim)
  182. else:
  183. if axis is None:
  184. axis = []
  185. else:
  186. axis = [axis]
  187. attrs = {'axis': axis, 'dtype': dtype, 'keepdim': keepdim}
  188. if dtype_flag:
  189. attrs.update({'in_dtype': x.dtype, 'out_dtype': dtype})
  190. check_variable_and_dtype(
  191. x,
  192. 'x',
  193. [
  194. 'bool',
  195. 'float32',
  196. 'float64',
  197. 'int16',
  198. 'int32',
  199. 'int64',
  200. ],
  201. 'sparse_sum',
  202. )
  203. check_type(
  204. axis, 'axis', (int, list, tuple, type(None), Variable), 'sparse_sum'
  205. )
  206. op_type = 'sparse_sum'
  207. helper = LayerHelper(op_type)
  208. if dtype_flag:
  209. out = helper.create_sparse_variable_for_type_inference(dtype=dtype)
  210. else:
  211. out = helper.create_sparse_variable_for_type_inference(
  212. dtype=x.dtype
  213. )
  214. helper.append_op(
  215. type=op_type, inputs={'x': x}, outputs={'out': out}, attrs=attrs
  216. )
  217. return out
  218. @dygraph_only
  219. def atan(x, name=None):
  220. """
  221. Calculate elementwise atan of SparseTensor, requiring x to be a SparseCooTensor or SparseCsrTensor.
  222. .. math::
  223. out = atan(x)
  224. Parameters:
  225. x (Tensor): The input Sparse Tensor with data type float32, float64.
  226. name (str, optional): Name for the operation (optional, default is None).
  227. For more information, please refer to :ref:`api_guide_Name`.
  228. Returns:
  229. A Sparse Tensor with the same data type and shape as ``x`` .
  230. Examples:
  231. .. code-block:: python
  232. >>> import paddle
  233. >>> dense_x = paddle.to_tensor([-2., 0., 1.])
  234. >>> sparse_x = dense_x.to_sparse_coo(1)
  235. >>> out = paddle.sparse.atan(sparse_x)
  236. >>> out
  237. Tensor(shape=[3], dtype=paddle.float32, place=Place(cpu), stop_gradient=True,
  238. indices=[[0, 2]],
  239. values=[-1.10714877, 0.78539819])
  240. """
  241. return _C_ops.sparse_atan(x)
  242. @dygraph_only
  243. def sinh(x, name=None):
  244. """
  245. Calculate elementwise sinh of SparseTensor, requiring x to be a SparseCooTensor or SparseCsrTensor.
  246. .. math::
  247. out = sinh(x)
  248. Parameters:
  249. x (Tensor): The input Sparse Tensor with data type float32, float64.
  250. name (str, optional): Name for the operation (optional, default is None).
  251. For more information, please refer to :ref:`api_guide_Name`.
  252. Returns:
  253. A Sparse Tensor with the same data type and shape as ``x`` .
  254. Examples:
  255. .. code-block:: python
  256. >>> import paddle
  257. >>> dense_x = paddle.to_tensor([-2., 0., 1.])
  258. >>> sparse_x = dense_x.to_sparse_coo(1)
  259. >>> out = paddle.sparse.sinh(sparse_x)
  260. >>> out
  261. Tensor(shape=[3], dtype=paddle.float32, place=Place(cpu), stop_gradient=True,
  262. indices=[[0, 2]],
  263. values=[-3.62686038, 1.17520118])
  264. """
  265. return _C_ops.sparse_sinh(x)
  266. @dygraph_only
  267. def asinh(x, name=None):
  268. """
  269. Calculate elementwise asinh of SparseTensor, requiring x to be a SparseCooTensor or SparseCsrTensor.
  270. .. math::
  271. out = asinh(x)
  272. Parameters:
  273. x (Tensor): The input Sparse Tensor with data type float32, float64.
  274. name (str, optional): Name for the operation (optional, default is None).
  275. For more information, please refer to :ref:`api_guide_Name`.
  276. Returns:
  277. A Sparse Tensor with the same data type and shape as ``x`` .
  278. Examples:
  279. .. code-block:: python
  280. >>> import paddle
  281. >>> dense_x = paddle.to_tensor([-2., 0., 1.])
  282. >>> sparse_x = dense_x.to_sparse_coo(1)
  283. >>> out = paddle.sparse.asinh(sparse_x)
  284. >>> out
  285. Tensor(shape=[3], dtype=paddle.float32, place=Place(cpu), stop_gradient=True,
  286. indices=[[0, 2]],
  287. values=[-1.44363546, 0.88137358])
  288. """
  289. return _C_ops.sparse_asinh(x)
  290. @dygraph_only
  291. def atanh(x, name=None):
  292. """
  293. Calculate elementwise atanh of SparseTensor, requiring x to be a SparseCooTensor or SparseCsrTensor.
  294. .. math::
  295. out = atanh(x)
  296. Parameters:
  297. x (Tensor): The input Sparse Tensor with data type float32, float64.
  298. name (str, optional): Name for the operation (optional, default is None).
  299. For more information, please refer to :ref:`api_guide_Name`.
  300. Returns:
  301. A Sparse Tensor with the same data type and shape as ``x`` .
  302. Examples:
  303. .. code-block:: python
  304. >>> import paddle
  305. >>> dense_x = paddle.to_tensor([-2., 0., 1.])
  306. >>> sparse_x = dense_x.to_sparse_coo(1)
  307. >>> out = paddle.sparse.atanh(sparse_x)
  308. >>> out
  309. Tensor(shape=[3], dtype=paddle.float32, place=Place(cpu), stop_gradient=True,
  310. indices=[[0, 2]],
  311. values=[nan , inf.])
  312. """
  313. return _C_ops.sparse_atanh(x)
  314. @dygraph_only
  315. def tanh(x, name=None):
  316. """
  317. Calculate elementwise tanh of SparseTensor, requiring x to be a SparseCooTensor or SparseCsrTensor.
  318. .. math::
  319. out = tanh(x)
  320. Parameters:
  321. x (Tensor): The input Sparse Tensor with data type float32, float64.
  322. name (str, optional): Name for the operation (optional, default is None).
  323. For more information, please refer to :ref:`api_guide_Name`.
  324. Returns:
  325. A Sparse Tensor with the same data type and shape as ``x`` .
  326. Examples:
  327. .. code-block:: python
  328. >>> import paddle
  329. >>> dense_x = paddle.to_tensor([-2., 0., 1.])
  330. >>> sparse_x = dense_x.to_sparse_coo(1)
  331. >>> out = paddle.sparse.tanh(sparse_x)
  332. >>> out
  333. Tensor(shape=[3], dtype=paddle.float32, place=Place(cpu), stop_gradient=True,
  334. indices=[[0, 2]],
  335. values=[-0.96402758, 0.76159418])
  336. """
  337. return _C_ops.sparse_tanh(x)
  338. @dygraph_only
  339. def square(x, name=None):
  340. """
  341. Calculate elementwise square of SparseTensor, requiring x to be a SparseCooTensor or SparseCsrTensor.
  342. .. math::
  343. out = square(x)
  344. Parameters:
  345. x (Tensor): The input Sparse Tensor with data type float32, float64.
  346. name (str, optional): Name for the operation (optional, default is None).
  347. For more information, please refer to :ref:`api_guide_Name`.
  348. Returns:
  349. A Sparse Tensor with the same data type and shape as ``x`` .
  350. Examples:
  351. .. code-block:: python
  352. >>> import paddle
  353. >>> dense_x = paddle.to_tensor([-2., 0., 1.])
  354. >>> sparse_x = dense_x.to_sparse_coo(1)
  355. >>> out = paddle.sparse.square(sparse_x)
  356. >>> out
  357. Tensor(shape=[3], dtype=paddle.float32, place=Place(cpu), stop_gradient=True,
  358. indices=[[0, 2]],
  359. values=[4., 1.])
  360. """
  361. return _C_ops.sparse_square(x)
  362. @dygraph_only
  363. def sqrt(x, name=None):
  364. """
  365. Calculate elementwise sqrt of SparseTensor, requiring x to be a SparseCooTensor or SparseCsrTensor.
  366. .. math::
  367. out = sqrt(x)
  368. Parameters:
  369. x (Tensor): The input Sparse Tensor with data type float32, float64.
  370. name (str, optional): Name for the operation (optional, default is None).
  371. For more information, please refer to :ref:`api_guide_Name`.
  372. Returns:
  373. A Sparse Tensor with the same data type and shape as ``x`` .
  374. Examples:
  375. .. code-block:: python
  376. >>> import paddle
  377. >>> dense_x = paddle.to_tensor([-2., 0., 1.])
  378. >>> sparse_x = dense_x.to_sparse_coo(1)
  379. >>> out = paddle.sparse.sqrt(sparse_x)
  380. >>> out
  381. Tensor(shape=[3], dtype=paddle.float32, place=Place(cpu), stop_gradient=True,
  382. indices=[[0, 2]],
  383. values=[nan, 1. ])
  384. """
  385. return _C_ops.sparse_sqrt(x)
  386. @dygraph_only
  387. def log1p(x, name=None):
  388. """
  389. Calculate the natural log of (1+x), requiring x to be a SparseCooTensor or SparseCsrTensor.
  390. .. math::
  391. out = ln(1+x)
  392. Parameters:
  393. x (Tensor): The input Sparse Tensor with data type float32, float64.
  394. name (str, optional): Name for the operation (optional, default is None).
  395. For more information, please refer to :ref:`api_guide_Name`.
  396. Returns:
  397. A Sparse Tensor with the same data type and shape as ``x`` .
  398. Examples:
  399. .. code-block:: python
  400. >>> import paddle
  401. >>> dense_x = paddle.to_tensor([-2, 0, 1], dtype='float32')
  402. >>> sparse_x = dense_x.to_sparse_coo(1)
  403. >>> out = paddle.sparse.log1p(sparse_x)
  404. >>> out
  405. Tensor(shape=[3], dtype=paddle.float32, place=Place(cpu), stop_gradient=True,
  406. indices=[[0, 2]],
  407. values=[nan , 0.69314718])
  408. """
  409. return _C_ops.sparse_log1p(x)
  410. @dygraph_only
  411. def cast(x, index_dtype=None, value_dtype=None, name=None):
  412. """
  413. cast non-zero-index of SparseTensor to `index_dtype`, non-zero-element of SparseTensor to
  414. `value_dtype` , requiring x to be a SparseCooTensor or SparseCsrTensor.
  415. Parameters:
  416. x (Tensor): The input Sparse Tensor with data type float32, float64.
  417. index_dtype (np.dtype|str, optional): Data type of the index of SparseCooTensor,
  418. or crows/cols of SparseCsrTensor. Can be uint8, int8, int16, int32, int64.
  419. value_dtype (np.dtype|str, optional): Data type of the value of SparseCooTensor,
  420. SparseCsrTensor. Can be bool, float16, float32, float64, int8, int32, int64, uint8.
  421. name (str, optional): Name for the operation (optional, default is None).
  422. For more information, please refer to :ref:`api_guide_Name`.
  423. Returns:
  424. A Sparse Tensor with the same data type and shape as ``x`` .
  425. Examples:
  426. .. code-block:: python
  427. >>> import paddle
  428. >>> dense_x = paddle.to_tensor([-2, 0, 1])
  429. >>> sparse_x = dense_x.to_sparse_coo(1)
  430. >>> out = paddle.sparse.cast(sparse_x, 'int32', 'float64')
  431. >>> out
  432. Tensor(shape=[3], dtype=paddle.float64, place=Place(cpu), stop_gradient=True,
  433. indices=[[0, 2]],
  434. values=[-2., 1.])
  435. """
  436. if index_dtype and not isinstance(index_dtype, core.VarDesc.VarType):
  437. index_dtype = convert_np_dtype_to_dtype_(index_dtype)
  438. if value_dtype and not isinstance(value_dtype, core.VarDesc.VarType):
  439. value_dtype = convert_np_dtype_to_dtype_(value_dtype)
  440. return _C_ops.sparse_cast(x, index_dtype, value_dtype)
  441. @dygraph_only
  442. def pow(x, factor, name=None):
  443. """
  444. Calculate elementwise pow of x, requiring x to be a SparseCooTensor or SparseCsrTensor.
  445. .. math::
  446. out = x^{factor}
  447. Parameters:
  448. x (Tensor): The input Sparse Tensor with data type float32, float64.
  449. factor (float|int): factor of pow.
  450. name (str, optional): Name for the operation (optional, default is None).
  451. For more information, please refer to :ref:`api_guide_Name`.
  452. Returns:
  453. A Sparse Tensor with the same data type and shape as ``x`` .
  454. Examples:
  455. .. code-block:: python
  456. >>> import paddle
  457. >>> dense_x = paddle.to_tensor([-2, 0, 3], dtype='float32')
  458. >>> sparse_x = dense_x.to_sparse_coo(1)
  459. >>> out = paddle.sparse.pow(sparse_x, 2)
  460. >>> out
  461. Tensor(shape=[3], dtype=paddle.float32, place=Place(cpu), stop_gradient=True,
  462. indices=[[0, 2]],
  463. values=[4., 9.])
  464. """
  465. return _C_ops.sparse_pow(x, float(factor))
  466. @dygraph_only
  467. def neg(x, name=None):
  468. """
  469. Calculate elementwise negative of x, requiring x to be a SparseCooTensor or SparseCsrTensor.
  470. .. math::
  471. out = -x
  472. Parameters:
  473. x (Tensor): The input Sparse Tensor with data type float32, float64.
  474. name (str, optional): Name for the operation (optional, default is None).
  475. For more information, please refer to :ref:`api_guide_Name`.
  476. Returns:
  477. A Sparse Tensor with the same data type and shape as ``x`` .
  478. Examples:
  479. .. code-block:: python
  480. >>> import paddle
  481. >>> dense_x = paddle.to_tensor([-2, 0, 3], dtype='float32')
  482. >>> sparse_x = dense_x.to_sparse_coo(1)
  483. >>> out = paddle.sparse.neg(sparse_x)
  484. >>> out
  485. Tensor(shape=[3], dtype=paddle.float32, place=Place(cpu), stop_gradient=True,
  486. indices=[[0, 2]],
  487. values=[ 2., -3.])
  488. """
  489. return _C_ops.sparse_scale(x, -1.0, 0.0, True)
  490. @dygraph_only
  491. def abs(x, name=None):
  492. """
  493. Calculate elementwise absolute value of x, requiring x to be a SparseCooTensor or SparseCsrTensor.
  494. .. math::
  495. out = |x|
  496. Parameters:
  497. x (Tensor): The input Sparse Tensor with data type float32, float64, complex64, complex128.
  498. name (str, optional): Name for the operation (optional, default is None).
  499. For more information, please refer to :ref:`api_guide_Name`.
  500. Returns:
  501. A Sparse Tensor with the same data type and shape as ``x`` .
  502. Examples:
  503. .. code-block:: python
  504. >>> import paddle
  505. >>> dense_x = paddle.to_tensor([-2, 0, 3], dtype='float32')
  506. >>> sparse_x = dense_x.to_sparse_coo(1)
  507. >>> out = paddle.sparse.abs(sparse_x)
  508. >>> out
  509. Tensor(shape=[3], dtype=paddle.float32, place=Place(cpu), stop_gradient=True,
  510. indices=[[0, 2]],
  511. values=[2., 3.])
  512. """
  513. return _C_ops.sparse_abs(x)
  514. @dygraph_only
  515. def coalesce(x, name=None):
  516. r"""
  517. the coalesced operator include sorted and merge, after coalesced, the indices of x is sorted and unique.
  518. Parameters:
  519. x (Tensor): the input SparseCooTensor.
  520. name (str, optional): Name for the operation (optional, default is None).
  521. For more information, please refer to :ref:`api_guide_Name`.
  522. Returns:
  523. Tensor: return the SparseCooTensor after coalesced.
  524. Examples:
  525. .. code-block:: python
  526. >>> import paddle
  527. >>> indices = [[0, 0, 1], [1, 1, 2]]
  528. >>> values = [1.0, 2.0, 3.0]
  529. >>> sp_x = paddle.sparse.sparse_coo_tensor(indices, values)
  530. >>> sp_x = paddle.sparse.coalesce(sp_x)
  531. >>> print(sp_x.indices())
  532. Tensor(shape=[2, 2], dtype=int64, place=Place(cpu), stop_gradient=True,
  533. [[0, 1],
  534. [1, 2]])
  535. >>> print(sp_x.values())
  536. Tensor(shape=[2], dtype=float32, place=Place(cpu), stop_gradient=True,
  537. [3., 3.])
  538. """
  539. return _C_ops.sparse_coalesce(x)
  540. @dygraph_only
  541. def rad2deg(x, name=None):
  542. r"""
  543. Convert each of the elements of input x from radian to degree,
  544. requiring x to be a SparseCooTensor or SparseCsrTensor.
  545. .. math::
  546. rad2deg(x) = 180/ \pi * x
  547. Parameters:
  548. x (Tensor): The input Sparse Tensor with data type float32, float64, int32, int64.
  549. name (str, optional): Name for the operation (optional, default is None).
  550. For more information, please refer to :ref:`api_guide_Name`.
  551. Returns:
  552. A Sparse Tensor with the same data type and shape as ``x`` .
  553. Examples:
  554. .. code-block:: python
  555. >>> import paddle
  556. >>> dense_x = paddle.to_tensor([3.142, 0., -3.142])
  557. >>> sparse_x = dense_x.to_sparse_coo(1)
  558. >>> out = paddle.sparse.rad2deg(sparse_x)
  559. >>> out
  560. Tensor(shape=[3], dtype=paddle.float32, place=Place(cpu), stop_gradient=True,
  561. indices=[[0, 2]],
  562. values=[ 180.02334595, -180.02334595])
  563. """
  564. if x.dtype in _int_dtype_:
  565. x = _C_ops.sparse_cast(x, None, core.VarDesc.VarType.FP32)
  566. return _C_ops.sparse_scale(x, 180.0 / np.pi, 0.0, True)
  567. @dygraph_only
  568. def deg2rad(x, name=None):
  569. r"""
  570. Convert each of the elements of input x from degree to radian,
  571. requiring x to be a SparseCooTensor or SparseCsrTensor.
  572. .. math::
  573. deg2rad(x) = \pi * x / 180
  574. Parameters:
  575. x (Tensor): The input Sparse Tensor with data type float32, float64, int32, int64.
  576. name (str, optional): Name for the operation (optional, default is None).
  577. For more information, please refer to :ref:`api_guide_Name`.
  578. Returns:
  579. A Sparse Tensor with the same data type and shape as ``x`` .
  580. Examples:
  581. .. code-block:: python
  582. >>> import paddle
  583. >>> dense_x = paddle.to_tensor([-180, 0, 180])
  584. >>> sparse_x = dense_x.to_sparse_coo(1)
  585. >>> out = paddle.sparse.deg2rad(sparse_x)
  586. >>> out
  587. Tensor(shape=[3], dtype=paddle.float32, place=Place(cpu), stop_gradient=True,
  588. indices=[[0, 2]],
  589. values=[-3.14159274, 3.14159274])
  590. """
  591. if x.dtype in _int_dtype_:
  592. x = _C_ops.sparse_cast(x, None, core.VarDesc.VarType.FP32)
  593. return _C_ops.sparse_scale(x, np.pi / 180.0, 0.0, True)
  594. @dygraph_only
  595. def expm1(x, name=None):
  596. """
  597. Calculate elementwise `exp(x)-1` , requiring x to be a SparseCooTensor or SparseCsrTensor.
  598. .. math::
  599. out = exp(x) - 1
  600. Parameters:
  601. x (Tensor): The input Sparse Tensor with data type float32, float64.
  602. name (str, optional): Name for the operation (optional, default is None).
  603. For more information, please refer to :ref:`api_guide_Name`.
  604. Returns:
  605. A Sparse Tensor with the same data type and shape as ``x`` .
  606. Examples:
  607. .. code-block:: python
  608. >>> import paddle
  609. >>> dense_x = paddle.to_tensor([-2., 0., 1.])
  610. >>> sparse_x = dense_x.to_sparse_coo(1)
  611. >>> out = paddle.sparse.expm1(sparse_x)
  612. >>> out
  613. Tensor(shape=[3], dtype=paddle.float32, place=Place(cpu), stop_gradient=True,
  614. indices=[[0, 2]],
  615. values=[-0.86466473, 1.71828187])
  616. """
  617. return _C_ops.sparse_expm1(x)
  618. def reshape(x, shape, name=None):
  619. """
  620. Changes the shape of ``x`` without changing its value, requiring x to be a SparseCooTensor or SparseCsrTensor.
  621. Currently this function can only reshape the sparse dims of ``x`` , but ``shape`` argument must be specified
  622. as the shape of the reshaped tensor.
  623. Note that if x is a SparseCsrTensor, then len(shape) must be 2 or 3.
  624. There are some tricks when specifying the target shape.
  625. - 1. -1 means the value of this dimension is inferred from the total element number of x and remaining dimensions. Thus one and only one dimension can be set -1.
  626. - 2. 0 means the actual dimension value is going to be copied from the corresponding dimension of x. The indices of 0 in the target shape can not exceed the rank of x.
  627. Here are some examples to explain it.
  628. - 1. Given a 3-D tensor x with a shape [2, 4, 6], and the target shape is [6, 8], the reshape operator will transform x into a 2-D tensor with shape [6, 8] and leaving x's data unchanged.
  629. - 2. Given a 3-D tensor x with a shape [2, 4, 6], and the target shape is [2, 3, -1, 2], the reshape operator will transform x into a 4-D tensor with shape [2, 3, 4, 2] and leaving x's data unchanged. In this case, one dimension of the target shape is set to -1, the value of this dimension is inferred from the total element number of x and remaining dimensions.
  630. - 3. Given a 3-D tensor x with a shape [2, 4, 6], and the target shape is [-1, 0, 3, 2], the reshape operator will transform x into a 4-D tensor with shape [2, 4, 3, 2] and leaving x's data unchanged. In this case, besides -1, 0 means the actual dimension value is going to be copied from the corresponding dimension of x.
  631. Args:
  632. x (Tensor): The input sparse tensor with data type ``float32``, ``float64``, ``int32``, ``int64`` or ``bool``.
  633. shape (list|tuple): Define the target shape. At most one dimension of the target shape can be -1.
  634. The data type is ``int32``.
  635. name (str, optional): Name for the operation (optional, default is None).
  636. For more information, please refer to :ref:`api_guide_Name`.
  637. Returns:
  638. Tensor: A reshaped Tensor with the same data type as ``x``.
  639. Examples:
  640. .. code-block:: python
  641. >>> import paddle
  642. >>> x_shape = [6, 2, 3]
  643. >>> new_shape = [1, 0, 2, -1, 3]
  644. >>> format = "coo"
  645. >>> dense_x = paddle.randint(-100, 100, x_shape) * paddle.randint(0, 2, x_shape)
  646. >>> if format == "coo":
  647. ... sp_x = dense_x.to_sparse_coo(len(x_shape))
  648. >>> else:
  649. ... sp_x = dense_x.to_sparse_csr()
  650. >>> sp_out = paddle.sparse.reshape(sp_x, new_shape)
  651. >>> print(sp_out.shape)
  652. [1, 2, 2, 3, 3]
  653. """
  654. if in_dynamic_mode():
  655. return _C_ops.sparse_reshape(x, shape)
  656. else:
  657. check_variable_and_dtype(
  658. x,
  659. 'x',
  660. [
  661. 'float16',
  662. 'float32',
  663. 'float64',
  664. 'int16',
  665. 'int32',
  666. 'int64',
  667. 'bool',
  668. 'uint16',
  669. ],
  670. 'reshape',
  671. )
  672. check_type(shape, 'shape', (list, tuple), 'reshape')
  673. inputs = {"x": x}
  674. attrs = {"shape": shape}
  675. helper = LayerHelper('sparse_reshape')
  676. out = helper.create_sparse_variable_for_type_inference(x.dtype)
  677. helper.append_op(
  678. type='sparse_reshape',
  679. inputs=inputs,
  680. outputs={'out': out},
  681. attrs=attrs,
  682. )
  683. return out
  684. def isnan(x, name=None):
  685. """
  686. Return whether every element of input tensor is `NaN` or not, requiring x to be a SparseCooTensor or SparseCsrTensor.
  687. Args:
  688. x (Tensor): The input tensor (SparseCooTensor or SparseCsrTensor), it's data type should be float16, float32, float64, int32, int64.
  689. name (str, optional): Name for the operation (optional, default is None). For more information, please refer to :ref:`api_guide_Name`.
  690. Returns:
  691. A Sparse Tensor with the same shape as ``x``, the bool result which shows every element of `x` whether it is `NaN` or not.
  692. Examples:
  693. .. code-block:: python
  694. >>> import paddle
  695. >>> import numpy as np
  696. >>> format = "coo"
  697. >>> np_x = np.asarray([[[0., 0], [1., 2.]], [[0., 0], [3., float('nan')]]])
  698. >>> dense_x = paddle.to_tensor(np_x)
  699. >>> if format == "coo":
  700. ... sparse_x = dense_x.to_sparse_coo(len(np_x.shape))
  701. >>> else:
  702. ... sparse_x = dense_x.to_sparse_csr()
  703. ...
  704. >>> sparse_out = paddle.sparse.isnan(sparse_x)
  705. >>> print(sparse_out)
  706. Tensor(shape=[2, 2, 2], dtype=paddle.bool, place=Place(gpu:0), stop_gradient=True,
  707. indices=[[0, 0, 1, 1],
  708. [1, 1, 1, 1],
  709. [0, 1, 0, 1]],
  710. values=[False, False, False, True ])
  711. """
  712. if in_dynamic_mode():
  713. return _C_ops.sparse_isnan(x)
  714. else:
  715. op_type = 'sparse_isnan'
  716. helper = LayerHelper(op_type)
  717. out = helper.create_sparse_variable_for_type_inference(x.dtype)
  718. helper.append_op(
  719. type=op_type, inputs={'x': x}, outputs={'out': out}, attrs={}
  720. )
  721. return out
  722. def slice(x, axes, starts, ends, name=None):
  723. """
  724. This operator produces a slice of ``x`` along multiple axes for sparse tensors.
  725. Slice uses ``axes``, ``starts`` and ``ends`` attributes to specify the start and
  726. end dimension for each axis in the list of axes and Slice uses this information
  727. to slice the input sparse tensor (x). If a negative value is passed to
  728. ``starts`` or ``ends`` such as :math:`-i`, it represents the reverse position of
  729. the axis :math:`i-1` (here 0 is the initial position).
  730. If the value passed to ``starts`` or ``ends`` is greater than the number of elements
  731. in the dimension (n), it represents n.
  732. For slicing to the end of a dimension with unknown size, it is recommended to pass
  733. in INT_MAX. The size of ``axes`` must be equal to ``starts`` and ``ends``.
  734. Args:
  735. x (Tensor): The input Tensor (``SparseCooTensor`` or ``SparseCsrTensor``), it's data type should be ``float16``, ``float32``, ``float64``, ``int32``, ``int64``.
  736. axes (list|tuple|Tensor): The data type is ``int32``.If ``axes`` is a list or tuple, the elements of
  737. it should be integers or a 0-D Tensor with shape []. If ``axes`` is a Tensor, it should be a 1-D Tensor.
  738. Axes that `starts` and `ends` apply to.
  739. starts (list|tuple|Tensor): The data type is ``int32``. If ``starts`` is a list or tuple, the elements of
  740. it should be integers or a 0-D Tensor with shape []. If ``starts`` is a Tensor, it should be a 1-D Tensor.
  741. It represents starting indices of corresponding axis in ``axes``.
  742. ends (list|tuple|Tensor): The data type is ``int32``. If ``ends`` is a list or tuple, the elements of
  743. it should be integers or a 0-D Tensor with shape []. If ``ends`` is a Tensor, it should be a 1-D Tensor.
  744. It represents ending indices of corresponding axis in ``axes``.
  745. Returns:
  746. A Sparse Tensor. The data type is same as ``x``.
  747. Examples:
  748. .. code-block:: python
  749. >>> import paddle
  750. >>> import numpy as np
  751. >>> format = 'coo'
  752. >>> np_x = np.asarray([[4, 0, 7, 0], [0, 0, 5, 0], [-4, 2, 0, 0]])
  753. >>> dense_x = paddle.to_tensor(np_x)
  754. >>> if format == 'coo':
  755. ... sp_x = dense_x.to_sparse_coo(len(np_x.shape))
  756. >>> else:
  757. ... sp_x = dense_x.to_sparse_csr()
  758. ...
  759. >>> axes = [0, 1]
  760. >>> starts = [1, 0]
  761. >>> ends = [3, -2]
  762. >>> sp_out = paddle.sparse.slice(sp_x, axes, starts, ends)
  763. >>> # sp_out is x[1:3, 0:-2]
  764. >>> print(sp_out)
  765. Tensor(shape=[2, 2], dtype=paddle.int64, place=Place(cpu), stop_gradient=True,
  766. indices=[[1, 1],
  767. [0, 1]],
  768. values=[-4, 2])
  769. """
  770. if in_dynamic_mode():
  771. return _C_ops.sparse_slice(x, axes, starts, ends)
  772. else:
  773. attrs = {'axes': axes, 'starts': starts, 'ends': ends}
  774. check_variable_and_dtype(
  775. x,
  776. 'x',
  777. [
  778. 'bool',
  779. 'float32',
  780. 'float64',
  781. 'int16',
  782. 'int32',
  783. 'int64',
  784. ],
  785. 'sparse_slice',
  786. )
  787. check_type(axes, 'axes', (list, tuple), 'sparse_slice')
  788. check_type(starts, 'starts', (list, tuple), 'sparse_slice')
  789. check_type(ends, 'ends', (list, tuple), 'sparse_slice')
  790. op_type = 'sparse_slice'
  791. helper = LayerHelper(op_type)
  792. out = helper.create_sparse_variable_for_type_inference(dtype=x.dtype)
  793. helper.append_op(
  794. type=op_type, inputs={'x': x}, outputs={'out': out}, attrs=attrs
  795. )
  796. return out
  797. def pca_lowrank(x, q=None, center=True, niter=2, name=None):
  798. r"""
  799. Performs linear Principal Component Analysis (PCA) on a sparse matrix.
  800. Let :math:`X` be the input matrix or a batch of input matrices, the output should satisfies:
  801. .. math::
  802. X = U * diag(S) * V^{T}
  803. Args:
  804. x (Tensor): The input tensor. Its shape should be `[N, M]`,
  805. N and M can be arbitrary positive number.
  806. The data type of x should be float32 or float64.
  807. q (int, optional): a slightly overestimated rank of :math:`X`.
  808. Default value is :math:`q=min(6,N,M)`.
  809. center (bool, optional): if True, center the input tensor.
  810. Default value is True.
  811. name (str, optional): Name for the operation (optional, default is None).
  812. For more information, please refer to :ref:`api_guide_Name`.
  813. Returns:
  814. - Tensor U, is N x q matrix.
  815. - Tensor S, is a vector with length q.
  816. - Tensor V, is M x q matrix.
  817. tuple (U, S, V): which is the nearly optimal approximation of a singular value decomposition of a centered matrix :math:`X`.
  818. Examples:
  819. .. code-block:: python
  820. >>> # doctest: +REQUIRES(env:GPU)
  821. >>> import paddle
  822. >>> paddle.device.set_device('gpu')
  823. >>> format = "coo"
  824. >>> paddle.seed(2023)
  825. >>> dense_x = paddle.randn((5, 5), dtype='float64')
  826. >>> if format == "coo":
  827. ... sparse_x = dense_x.to_sparse_coo(len(dense_x.shape))
  828. >>> else:
  829. ... sparse_x = dense_x.to_sparse_csr()
  830. >>> print("sparse.pca_lowrank API only support CUDA 11.x")
  831. >>> # U, S, V = None, None, None
  832. >>> # use code blow when your device CUDA version >= 11.0
  833. >>> U, S, V = paddle.sparse.pca_lowrank(sparse_x)
  834. >>> print(U)
  835. Tensor(shape=[5, 5], dtype=float64, place=Place(gpu:0), stop_gradient=True,
  836. [[-0.31412600, 0.44814876, 0.18390454, -0.19967630, -0.79170452],
  837. [-0.31412600, 0.44814876, 0.18390454, -0.58579808, 0.56877700],
  838. [-0.31412600, 0.44814876, 0.18390454, 0.78547437, 0.22292751],
  839. [-0.38082462, 0.10982129, -0.91810233, 0.00000000, 0.00000000],
  840. [ 0.74762770, 0.62082796, -0.23585052, 0.00000000, -0.00000000]])
  841. >>> print(S)
  842. Tensor(shape=[5], dtype=float64, place=Place(gpu:0), stop_gradient=True,
  843. [1.56031096, 1.12956227, 0.27922715, 0.00000000, 0.00000000])
  844. >>> print(V)
  845. Tensor(shape=[5, 5], dtype=float64, place=Place(gpu:0), stop_gradient=True,
  846. [[ 0.88568469, -0.29081908, 0.06163676, 0.19597228, -0.29796422],
  847. [-0.26169364, -0.27616183, 0.43148760, -0.42522796, -0.69874939],
  848. [ 0.28587685, 0.30695344, -0.47790836, -0.76982533, -0.05501437],
  849. [-0.23958121, -0.62770647, -0.71141770, 0.11463224, -0.17125926],
  850. [ 0.08918713, -0.59238761, 0.27478686, -0.41833534, 0.62498824]])
  851. """
  852. def get_floating_dtype(x):
  853. dtype = x.dtype
  854. if dtype in (paddle.float16, paddle.float32, paddle.float64):
  855. return dtype
  856. return paddle.float32
  857. def conjugate(x):
  858. if x.is_complex():
  859. return x.conj()
  860. return x
  861. def transpose(x):
  862. shape = x.shape
  863. perm = list(range(0, len(shape)))
  864. perm = perm[:-2] + [perm[-1]] + [perm[-2]]
  865. if x.is_sparse():
  866. return paddle.sparse.transpose(x, perm)
  867. return paddle.transpose(x, perm)
  868. def transjugate(x):
  869. return conjugate(transpose(x))
  870. def get_approximate_basis(x, q, niter=2, M=None):
  871. niter = 2 if niter is None else niter
  872. m, n = x.shape[-2:]
  873. qr = paddle.linalg.qr
  874. R = paddle.randn((n, q), dtype=x.dtype)
  875. A_t = transpose(x)
  876. A_H = conjugate(A_t)
  877. if M is None:
  878. Q = qr(paddle.sparse.matmul(x, R))[0]
  879. for i in range(niter):
  880. Q = qr(paddle.sparse.matmul(A_H, Q))[0]
  881. Q = qr(paddle.sparse.matmul(x, Q))[0]
  882. else:
  883. M_H = transjugate(M)
  884. Q = qr(paddle.sparse.matmul(x, R) - paddle.matmul(M, R))[0]
  885. for i in range(niter):
  886. Q = qr(paddle.sparse.matmul(A_H, Q) - paddle.matmul(M_H, Q))[0]
  887. Q = qr(paddle.sparse.matmul(x, Q) - paddle.matmul(M, Q))[0]
  888. return Q
  889. def svd_lowrank(x, q=6, niter=2, M=None):
  890. q = 6 if q is None else q
  891. m, n = x.shape[-2:]
  892. if M is None:
  893. M_t = None
  894. else:
  895. M_t = transpose(M)
  896. A_t = transpose(x)
  897. if m < n or n > q:
  898. Q = get_approximate_basis(A_t, q, niter=niter, M=M_t)
  899. Q_c = conjugate(Q)
  900. if M is None:
  901. B_t = paddle.sparse.matmul(x, Q_c)
  902. else:
  903. B_t = paddle.sparse.matmul(x, Q_c) - paddle.matmul(M, Q_c)
  904. assert B_t.shape[-2] == m, (B_t.shape, m)
  905. assert B_t.shape[-1] == q, (B_t.shape, q)
  906. assert B_t.shape[-1] <= B_t.shape[-2], B_t.shape
  907. U, S, Vh = paddle.linalg.svd(B_t, full_matrices=False)
  908. V = transjugate(Vh)
  909. V = Q.matmul(V)
  910. else:
  911. Q = get_approximate_basis(x, q, niter=niter, M=M)
  912. Q_c = conjugate(Q)
  913. if M is None:
  914. B = paddle.sparse.matmul(A_t, Q_c)
  915. else:
  916. B = paddle.sparse.matmul(A_t, Q_c) - paddle.matmul(M_t, Q_c)
  917. B_t = transpose(B)
  918. assert B_t.shape[-2] == q, (B_t.shape, q)
  919. assert B_t.shape[-1] == n, (B_t.shape, n)
  920. assert B_t.shape[-1] <= B_t.shape[-2], B_t.shape
  921. U, S, Vh = paddle.linalg.svd(B_t, full_matrices=False)
  922. V = transjugate(Vh)
  923. U = Q.matmul(U)
  924. return U, S, V
  925. if not paddle.is_tensor(x):
  926. raise ValueError(f'Input must be tensor, but got {type(x)}')
  927. if not x.is_sparse():
  928. raise ValueError('Input must be sparse, but got dense')
  929. cuda_version = paddle.version.cuda()
  930. if (
  931. cuda_version is None
  932. or cuda_version == 'False'
  933. or int(cuda_version.split('.')[0]) < 11
  934. ):
  935. raise ValueError('sparse.pca_lowrank API only support CUDA 11.x')
  936. (m, n) = x.shape[-2:]
  937. if q is None:
  938. q = min(6, m, n)
  939. elif not (q >= 0 and q <= min(m, n)):
  940. raise ValueError(
  941. f'q(={q}) must be non-negative integer'
  942. f' and not greater than min(m, n)={min(m, n)}'
  943. )
  944. if not (niter >= 0):
  945. raise ValueError(f'niter(={niter}) must be non-negative integer')
  946. dtype = get_floating_dtype(x)
  947. if not center:
  948. return svd_lowrank(x, q, niter=niter, M=None)
  949. if len(x.shape) != 2:
  950. raise ValueError('input is expected to be 2-dimensional tensor')
  951. # TODO: complement sparse_csr_tensor test
  952. # when sparse.sum with axis(-2) is implemented
  953. s_sum = paddle.sparse.sum(x, axis=-2)
  954. s_val = s_sum.values() / m
  955. c = paddle.sparse.sparse_coo_tensor(
  956. s_sum.indices(), s_val, dtype=s_sum.dtype, place=s_sum.place
  957. )
  958. column_indices = c.indices()[0]
  959. indices = paddle.zeros((2, len(column_indices)), dtype=column_indices.dtype)
  960. indices[0] = column_indices
  961. C_t = paddle.sparse.sparse_coo_tensor(
  962. indices, c.values(), (n, 1), dtype=dtype, place=x.place
  963. )
  964. ones_m1_t = paddle.ones(x.shape[:-2] + [1, m], dtype=dtype)
  965. M = transpose(paddle.matmul(C_t.to_dense(), ones_m1_t))
  966. return svd_lowrank(x, q, niter=niter, M=M)