/pygraphblas/cdef/usercomplex.c

https://github.com/michelp/pygraphblas · C · 547 lines · 295 code · 115 blank · 137 comment · 18 complexity · 743f1d491bc3a683e20378fe856016f5 MD5 · raw file

  1. //------------------------------------------------------------------------------
  2. // GraphBLAS/Demo/Source/usercomplex.c: complex numbers as a user-defined type
  3. //------------------------------------------------------------------------------
  4. //------------------------------------------------------------------------------
  5. // GraphBLAS/Demo/Include/usercomplex.h: complex numbers as a user-defined type
  6. //------------------------------------------------------------------------------
  7. #ifndef USERCOMPLEX_H
  8. #define USERCOMPLEX_H
  9. #include "GraphBLAS.h"
  10. #include <complex.h>
  11. #ifndef CMPLX
  12. #define CMPLX(real,imag) \
  13. ( \
  14. (double _Complex)((double)(real)) + \
  15. (double _Complex)((double)(imag) * _Complex_I) \
  16. )
  17. #endif
  18. // "I" is used in GraphBLAS to denote a list of row indices; remove it here
  19. #undef I
  20. //------------------------------------------------------------------------------
  21. // 10 binary functions, z=f(x,y), where CxC -> C
  22. //------------------------------------------------------------------------------
  23. extern
  24. GrB_BinaryOp Complex_first , Complex_second , Complex_min ,
  25. Complex_max , Complex_plus , Complex_minus ,
  26. Complex_times , Complex_div , Complex_rdiv ,
  27. Complex_rminus, Complex_pair ;
  28. //------------------------------------------------------------------------------
  29. // 6 binary comparison functions, z=f(x,y), where CxC -> C
  30. //------------------------------------------------------------------------------
  31. extern
  32. GrB_BinaryOp Complex_iseq , Complex_isne ,
  33. Complex_isgt , Complex_islt ,
  34. Complex_isge , Complex_isle ;
  35. //------------------------------------------------------------------------------
  36. // 3 binary boolean functions, z=f(x,y), where CxC -> C
  37. //------------------------------------------------------------------------------
  38. extern
  39. GrB_BinaryOp Complex_or , Complex_and , Complex_xor ;
  40. //------------------------------------------------------------------------------
  41. // 6 binary comparison functions, z=f(x,y), where CxC -> bool
  42. //------------------------------------------------------------------------------
  43. extern
  44. GrB_BinaryOp Complex_eq , Complex_ne ,
  45. Complex_gt , Complex_lt ,
  46. Complex_ge , Complex_le ;
  47. //------------------------------------------------------------------------------
  48. // 1 binary function, z=f(x,y), where double x double -> C
  49. //------------------------------------------------------------------------------
  50. extern GrB_BinaryOp Complex_complex ;
  51. //------------------------------------------------------------------------------
  52. // 5 unary functions, z=f(x) where C -> C
  53. //------------------------------------------------------------------------------
  54. extern
  55. GrB_UnaryOp Complex_identity , Complex_ainv , Complex_minv ,
  56. Complex_not , Complex_conj,
  57. Complex_one , Complex_abs ;
  58. //------------------------------------------------------------------------------
  59. // 4 unary functions, z=f(x) where C -> double
  60. //------------------------------------------------------------------------------
  61. extern
  62. GrB_UnaryOp Complex_real, Complex_imag,
  63. Complex_cabs, Complex_angle ;
  64. //------------------------------------------------------------------------------
  65. // 2 unary functions, z=f(x) where double -> C
  66. //------------------------------------------------------------------------------
  67. extern GrB_UnaryOp Complex_complex_real, Complex_complex_imag ;
  68. //------------------------------------------------------------------------------
  69. // Complex type, scalars, monoids, and semiring
  70. //------------------------------------------------------------------------------
  71. #ifdef MY_COMPLEX
  72. // use the pre-defined type in User/my_complex.m4
  73. #define Complex My_Complex
  74. #else
  75. extern GrB_Type Complex ;
  76. #endif
  77. extern GrB_Monoid Complex_plus_monoid, Complex_times_monoid ;
  78. extern GrB_Semiring Complex_plus_times ;
  79. extern double _Complex Complex_1 ;
  80. extern double _Complex Complex_0 ;
  81. GrB_Info Complex_init ( ) ;
  82. GrB_Info Complex_finalize ( ) ;
  83. #endif
  84. #if defined __INTEL_COMPILER
  85. #pragma warning (disable: 58 167 144 161 177 181 186 188 589 593 869 981 1418 1419 1572 1599 2259 2282 2557 2547 3280 )
  86. #elif defined __GNUC__
  87. #pragma GCC diagnostic ignored "-Wunused-parameter"
  88. #pragma GCC diagnostic ignored "-Wincompatible-pointer-types"
  89. #endif
  90. #define C double _Complex
  91. #define X *x
  92. #define Y *y
  93. #define Z *z
  94. #define ONE CMPLX(1,0)
  95. #define ZERO CMPLX(0,0)
  96. #define T ONE
  97. #define F ZERO
  98. #define BOOL(X) (X != ZERO)
  99. //------------------------------------------------------------------------------
  100. // binary functions, z=f(x,y), where CxC -> C
  101. //------------------------------------------------------------------------------
  102. void complex_first (C Z, const C X, const C Y) { Z = X ; }
  103. void complex_second (C Z, const C X, const C Y) { Z = Y ; }
  104. void complex_pair (C Z, const C X, const C Y) { Z = ONE ; }
  105. void complex_plus (C Z, const C X, const C Y) { Z = X + Y ; }
  106. void complex_minus (C Z, const C X, const C Y) { Z = X - Y ; }
  107. void complex_rminus (C Z, const C X, const C Y) { Z = Y - X ; }
  108. void complex_times (C Z, const C X, const C Y) { Z = X * Y ; }
  109. void complex_div (C Z, const C X, const C Y) { Z = X / Y ; }
  110. void complex_rdiv (C Z, const C X, const C Y) { Z = Y / X ; }
  111. void complex_min (C Z, const C X, const C Y)
  112. {
  113. // min (x,y): complex number with smallest magnitude. If tied, select the
  114. // one with the smallest phase angle (same as MATLAB definition).
  115. // No special cases for NaNs.
  116. double absx = cabs (X) ;
  117. double absy = cabs (Y) ;
  118. if (absx < absy)
  119. {
  120. Z = X ;
  121. }
  122. else if (absx > absy)
  123. {
  124. Z = Y ;
  125. }
  126. else
  127. {
  128. if (carg (X) < carg (Y))
  129. {
  130. Z = X ;
  131. }
  132. else
  133. {
  134. Z = Y ;
  135. }
  136. }
  137. }
  138. void complex_max (C Z, const C X, const C Y)
  139. {
  140. // max (x,y): complex number with largest magnitude. If tied, select the
  141. // one with the largest phase angle (same as MATLAB definition).
  142. // No special cases for NaNs.
  143. double absx = cabs (X) ;
  144. double absy = cabs (Y) ;
  145. if (absx > absy)
  146. {
  147. Z = X ;
  148. }
  149. else if (absx < absy)
  150. {
  151. Z = Y ;
  152. }
  153. else
  154. {
  155. if (carg (X) > carg (Y))
  156. {
  157. Z = X ;
  158. }
  159. else
  160. {
  161. Z = Y ;
  162. }
  163. }
  164. }
  165. GrB_BinaryOp Complex_first = NULL, Complex_second = NULL, Complex_min = NULL,
  166. Complex_max = NULL, Complex_plus = NULL, Complex_minus = NULL,
  167. Complex_times = NULL, Complex_div = NULL, Complex_rminus = NULL,
  168. Complex_rdiv = NULL, Complex_pair = NULL ;
  169. //------------------------------------------------------------------------------
  170. // 6 binary functions, z=f(x,y), where CxC -> C ; (1,0) = true, (0,0) = false
  171. //------------------------------------------------------------------------------
  172. // inequality operators follow the MATLAB convention
  173. #define R(x) creal(x)
  174. void complex_iseq (C Z, const C X, const C Y) { Z = (X == Y) ? T : F ; }
  175. void complex_isne (C Z, const C X, const C Y) { Z = (X != Y) ? T : F ; }
  176. void complex_isgt (C Z, const C X, const C Y) { Z = (R(X) > R(Y)) ? T : F ; }
  177. void complex_islt (C Z, const C X, const C Y) { Z = (R(X) < R(Y)) ? T : F ; }
  178. void complex_isge (C Z, const C X, const C Y) { Z = (R(X) >= R(Y)) ? T : F ; }
  179. void complex_isle (C Z, const C X, const C Y) { Z = (R(X) <= R(Y)) ? T : F ; }
  180. GrB_BinaryOp Complex_iseq = NULL, Complex_isne = NULL,
  181. Complex_isgt = NULL, Complex_islt = NULL,
  182. Complex_isge = NULL, Complex_isle = NULL ;
  183. //------------------------------------------------------------------------------
  184. // binary boolean functions, z=f(x,y), where CxC -> C
  185. //------------------------------------------------------------------------------
  186. void complex_or (C Z, const C X, const C Y)
  187. {
  188. Z = (BOOL (X) || BOOL (Y)) ? T : F ;
  189. }
  190. void complex_and (C Z, const C X, const C Y)
  191. {
  192. Z = (BOOL (X) && BOOL (Y)) ? T : F ;
  193. }
  194. void complex_xor (C Z, const C X, const C Y)
  195. {
  196. Z = (BOOL (X) != BOOL (Y)) ? T : F ;
  197. }
  198. GrB_BinaryOp Complex_or = NULL, Complex_and = NULL, Complex_xor = NULL ;
  199. //------------------------------------------------------------------------------
  200. // 6 binary functions, z=f(x,y), where CxC -> bool
  201. //------------------------------------------------------------------------------
  202. // inequality operators follow the MATLAB convention
  203. void complex_eq (bool Z, const C X, const C Y) { Z = (X == Y) ; }
  204. void complex_ne (bool Z, const C X, const C Y) { Z = (X != Y) ; }
  205. void complex_gt (bool Z, const C X, const C Y) { Z = (R (X) > R (Y)) ;}
  206. void complex_lt (bool Z, const C X, const C Y) { Z = (R (X) < R (Y)) ;}
  207. void complex_ge (bool Z, const C X, const C Y) { Z = (R (X) >= R (Y)) ;}
  208. void complex_le (bool Z, const C X, const C Y) { Z = (R (X) <= R (Y)) ;}
  209. GrB_BinaryOp Complex_eq = NULL, Complex_ne = NULL,
  210. Complex_gt = NULL, Complex_lt = NULL,
  211. Complex_ge = NULL, Complex_le = NULL ;
  212. //------------------------------------------------------------------------------
  213. // binary functions, z=f(x,y), where double x double -> complex
  214. //------------------------------------------------------------------------------
  215. void complex_complex (C Z, const double X, const double Y) { Z = CMPLX (X,Y) ; }
  216. GrB_BinaryOp Complex_complex = NULL ;
  217. //------------------------------------------------------------------------------
  218. // unary functions, z=f(x) where C -> C
  219. //------------------------------------------------------------------------------
  220. void complex_one (C Z, const C X) { Z = 1. ; }
  221. void complex_identity (C Z, const C X) { Z = X ; }
  222. void complex_ainv (C Z, const C X) { Z = -X ; }
  223. void complex_abs (C Z, const C X) { Z = CMPLX (cabs (X), 0) ; }
  224. void complex_minv (C Z, const C X) { Z = 1. / X ; }
  225. void complex_not (C Z, const C X) { Z = BOOL (X) ? F : T ; }
  226. void complex_conj (C Z, const C X) { Z = conj (X) ; }
  227. GrB_UnaryOp Complex_identity = NULL, Complex_ainv = NULL, Complex_minv = NULL,
  228. Complex_not = NULL, Complex_conj = NULL,
  229. Complex_one = NULL, Complex_abs = NULL ;
  230. //------------------------------------------------------------------------------
  231. // unary functions, z=f(x) where C -> double
  232. //------------------------------------------------------------------------------
  233. void complex_real (double Z, const C X) { Z = creal (X) ; }
  234. void complex_imag (double Z, const C X) { Z = cimag (X) ; }
  235. void complex_cabs (double Z, const C X) { Z = cabs (X) ; }
  236. void complex_angle (double Z, const C X) { Z = carg (X) ; }
  237. GrB_UnaryOp Complex_real = NULL, Complex_imag = NULL,
  238. Complex_cabs = NULL, Complex_angle = NULL ;
  239. //------------------------------------------------------------------------------
  240. // unary functions, z=f(x) where double -> C
  241. //------------------------------------------------------------------------------
  242. void complex_complex_real (C Z, const double X) { Z = CMPLX (X, 0) ; }
  243. void complex_complex_imag (C Z, const double X) { Z = CMPLX (0, X) ; }
  244. GrB_UnaryOp Complex_complex_real = NULL, Complex_complex_imag = NULL ;
  245. //------------------------------------------------------------------------------
  246. // Complex type, scalars, monoids, and semiring
  247. //------------------------------------------------------------------------------
  248. #ifndef MY_COMPLEX
  249. GrB_Type Complex = NULL ;
  250. #endif
  251. GrB_Monoid Complex_plus_monoid = NULL, Complex_times_monoid = NULL ;
  252. GrB_Semiring Complex_plus_times = NULL ;
  253. C Complex_1 = ONE ;
  254. C Complex_0 = ZERO ;
  255. #define OK(method) \
  256. info = method ; \
  257. if (info != GrB_SUCCESS) \
  258. { \
  259. Complex_finalize ( ) ; \
  260. return (info) ; \
  261. }
  262. //------------------------------------------------------------------------------
  263. // Complex_init: create the complex type, operators, monoids, and semiring
  264. //------------------------------------------------------------------------------
  265. GrB_Info Complex_init ( )
  266. {
  267. GrB_Info info ;
  268. //--------------------------------------------------------------------------
  269. // create the Complex type
  270. //--------------------------------------------------------------------------
  271. #ifndef MY_COMPLEX
  272. OK (GrB_Type_new (&Complex, sizeof (C))) ;
  273. #endif
  274. #undef C
  275. #undef D
  276. #define C Complex
  277. #define D GrB_FP64
  278. //--------------------------------------------------------------------------
  279. // create the Complex binary operators, CxC->C
  280. //--------------------------------------------------------------------------
  281. OK (GrB_BinaryOp_new (&Complex_first , complex_first , C, C, C)) ;
  282. OK (GrB_BinaryOp_new (&Complex_second , complex_second , C, C, C)) ;
  283. OK (GrB_BinaryOp_new (&Complex_pair , complex_pair , C, C, C)) ;
  284. OK (GrB_BinaryOp_new (&Complex_min , complex_min , C, C, C)) ;
  285. OK (GrB_BinaryOp_new (&Complex_max , complex_max , C, C, C)) ;
  286. OK (GrB_BinaryOp_new (&Complex_plus , complex_plus , C, C, C)) ;
  287. OK (GrB_BinaryOp_new (&Complex_minus , complex_minus , C, C, C)) ;
  288. OK (GrB_BinaryOp_new (&Complex_rminus , complex_rminus , C, C, C)) ;
  289. OK (GrB_BinaryOp_new (&Complex_times , complex_times , C, C, C)) ;
  290. OK (GrB_BinaryOp_new (&Complex_div , complex_div , C, C, C)) ;
  291. OK (GrB_BinaryOp_new (&Complex_rdiv , complex_rdiv , C, C, C)) ;
  292. //--------------------------------------------------------------------------
  293. // create the Complex binary comparison operators, CxC -> C
  294. //--------------------------------------------------------------------------
  295. OK (GrB_BinaryOp_new (&Complex_iseq , complex_iseq , C, C, C)) ;
  296. OK (GrB_BinaryOp_new (&Complex_isne , complex_isne , C, C, C)) ;
  297. OK (GrB_BinaryOp_new (&Complex_isgt , complex_isgt , C, C, C)) ;
  298. OK (GrB_BinaryOp_new (&Complex_islt , complex_islt , C, C, C)) ;
  299. OK (GrB_BinaryOp_new (&Complex_isge , complex_isge , C, C, C)) ;
  300. OK (GrB_BinaryOp_new (&Complex_isle , complex_isle , C, C, C)) ;
  301. //--------------------------------------------------------------------------
  302. // create the Complex boolean operators, CxC -> C
  303. //--------------------------------------------------------------------------
  304. OK (GrB_BinaryOp_new (&Complex_or , complex_or , C, C, C)) ;
  305. OK (GrB_BinaryOp_new (&Complex_and , complex_and , C, C, C)) ;
  306. OK (GrB_BinaryOp_new (&Complex_xor , complex_xor , C, C, C)) ;
  307. //--------------------------------------------------------------------------
  308. // create the Complex binary operators, CxC -> bool
  309. //--------------------------------------------------------------------------
  310. OK (GrB_BinaryOp_new (&Complex_eq , complex_eq , GrB_BOOL, C, C)) ;
  311. OK (GrB_BinaryOp_new (&Complex_ne , complex_ne , GrB_BOOL, C, C)) ;
  312. OK (GrB_BinaryOp_new (&Complex_gt , complex_gt , GrB_BOOL, C, C)) ;
  313. OK (GrB_BinaryOp_new (&Complex_lt , complex_lt , GrB_BOOL, C, C)) ;
  314. OK (GrB_BinaryOp_new (&Complex_ge , complex_ge , GrB_BOOL, C, C)) ;
  315. OK (GrB_BinaryOp_new (&Complex_le , complex_le , GrB_BOOL, C, C)) ;
  316. //--------------------------------------------------------------------------
  317. // create the Complex binary operator, double x double -> C
  318. //--------------------------------------------------------------------------
  319. OK (GrB_BinaryOp_new (&Complex_complex, complex_complex, C, D, D)) ;
  320. //--------------------------------------------------------------------------
  321. // create the Complex unary operators, C->C
  322. //--------------------------------------------------------------------------
  323. OK (GrB_UnaryOp_new (&Complex_one , complex_one , C, C)) ;
  324. OK (GrB_UnaryOp_new (&Complex_identity, complex_identity, C, C)) ;
  325. OK (GrB_UnaryOp_new (&Complex_ainv , complex_ainv , C, C)) ;
  326. OK (GrB_UnaryOp_new (&Complex_abs , complex_abs , C, C)) ;
  327. OK (GrB_UnaryOp_new (&Complex_minv , complex_minv , C, C)) ;
  328. OK (GrB_UnaryOp_new (&Complex_not , complex_not , C, C)) ;
  329. OK (GrB_UnaryOp_new (&Complex_conj , complex_conj , C, C)) ;
  330. //--------------------------------------------------------------------------
  331. // create the unary functions, C -> double
  332. //--------------------------------------------------------------------------
  333. OK (GrB_UnaryOp_new (&Complex_real , complex_real , D, C)) ;
  334. OK (GrB_UnaryOp_new (&Complex_imag , complex_imag , D, C)) ;
  335. OK (GrB_UnaryOp_new (&Complex_cabs , complex_cabs , D, C)) ;
  336. OK (GrB_UnaryOp_new (&Complex_angle , complex_angle , D, C)) ;
  337. //--------------------------------------------------------------------------
  338. // create the unary functions, double -> C
  339. //--------------------------------------------------------------------------
  340. OK (GrB_UnaryOp_new (&Complex_complex_real , complex_complex_real , C, D)) ;
  341. OK (GrB_UnaryOp_new (&Complex_complex_imag , complex_complex_imag , C, D)) ;
  342. //--------------------------------------------------------------------------
  343. // create the Complex monoids
  344. //--------------------------------------------------------------------------
  345. OK (GrB_Monoid_new_UDT (&Complex_plus_monoid, Complex_plus, &Complex_0)) ;
  346. OK (GrB_Monoid_new_UDT (&Complex_times_monoid, Complex_times, &Complex_1)) ;
  347. //--------------------------------------------------------------------------
  348. // create the Complex plus-times semiring
  349. //--------------------------------------------------------------------------
  350. // more could be created, but this suffices for testing GraphBLAS
  351. OK (GrB_Semiring_new
  352. (&Complex_plus_times, Complex_plus_monoid, Complex_times)) ;
  353. return (GrB_SUCCESS) ;
  354. }
  355. //------------------------------------------------------------------------------
  356. // Complex_finalize: free all complex types, operators, monoids, and semiring
  357. //------------------------------------------------------------------------------
  358. GrB_Info Complex_finalize ( )
  359. {
  360. //--------------------------------------------------------------------------
  361. // free the Complex plus-times semiring
  362. //--------------------------------------------------------------------------
  363. GrB_Semiring_free (&Complex_plus_times) ;
  364. //--------------------------------------------------------------------------
  365. // free the Complex monoids
  366. //--------------------------------------------------------------------------
  367. GrB_Monoid_free (&Complex_plus_monoid ) ;
  368. GrB_Monoid_free (&Complex_times_monoid) ;
  369. //--------------------------------------------------------------------------
  370. // free the Complex binary operators, CxC->C
  371. //--------------------------------------------------------------------------
  372. GrB_BinaryOp_free (&Complex_first ) ;
  373. GrB_BinaryOp_free (&Complex_second) ;
  374. GrB_BinaryOp_free (&Complex_pair ) ;
  375. GrB_BinaryOp_free (&Complex_min ) ;
  376. GrB_BinaryOp_free (&Complex_max ) ;
  377. GrB_BinaryOp_free (&Complex_plus ) ;
  378. GrB_BinaryOp_free (&Complex_minus ) ;
  379. GrB_BinaryOp_free (&Complex_rminus) ;
  380. GrB_BinaryOp_free (&Complex_times ) ;
  381. GrB_BinaryOp_free (&Complex_div ) ;
  382. GrB_BinaryOp_free (&Complex_rdiv ) ;
  383. GrB_BinaryOp_free (&Complex_iseq) ;
  384. GrB_BinaryOp_free (&Complex_isne) ;
  385. GrB_BinaryOp_free (&Complex_isgt) ;
  386. GrB_BinaryOp_free (&Complex_islt) ;
  387. GrB_BinaryOp_free (&Complex_isge) ;
  388. GrB_BinaryOp_free (&Complex_isle) ;
  389. GrB_BinaryOp_free (&Complex_or) ;
  390. GrB_BinaryOp_free (&Complex_and) ;
  391. GrB_BinaryOp_free (&Complex_xor) ;
  392. //--------------------------------------------------------------------------
  393. // free the Complex binary operators, CxC -> bool
  394. //--------------------------------------------------------------------------
  395. GrB_BinaryOp_free (&Complex_eq) ;
  396. GrB_BinaryOp_free (&Complex_ne) ;
  397. GrB_BinaryOp_free (&Complex_gt) ;
  398. GrB_BinaryOp_free (&Complex_lt) ;
  399. GrB_BinaryOp_free (&Complex_ge) ;
  400. GrB_BinaryOp_free (&Complex_le) ;
  401. //--------------------------------------------------------------------------
  402. // free the Complex binary operator, double x double -> complex
  403. //--------------------------------------------------------------------------
  404. GrB_BinaryOp_free (&Complex_complex) ;
  405. //--------------------------------------------------------------------------
  406. // free the Complex unary operators, C->C
  407. //--------------------------------------------------------------------------
  408. GrB_UnaryOp_free (&Complex_one ) ;
  409. GrB_UnaryOp_free (&Complex_identity) ;
  410. GrB_UnaryOp_free (&Complex_ainv ) ;
  411. GrB_UnaryOp_free (&Complex_abs ) ;
  412. GrB_UnaryOp_free (&Complex_minv ) ;
  413. GrB_UnaryOp_free (&Complex_not ) ;
  414. GrB_UnaryOp_free (&Complex_conj ) ;
  415. //--------------------------------------------------------------------------
  416. // free the unary functions, C -> double
  417. //--------------------------------------------------------------------------
  418. GrB_UnaryOp_free (&Complex_real ) ;
  419. GrB_UnaryOp_free (&Complex_imag ) ;
  420. GrB_UnaryOp_free (&Complex_cabs ) ;
  421. GrB_UnaryOp_free (&Complex_angle) ;
  422. //--------------------------------------------------------------------------
  423. // free the unary functions, double -> C
  424. //--------------------------------------------------------------------------
  425. GrB_UnaryOp_free (&Complex_complex_real) ;
  426. GrB_UnaryOp_free (&Complex_complex_imag) ;
  427. //--------------------------------------------------------------------------
  428. // free the Complex type
  429. //--------------------------------------------------------------------------
  430. GrB_Type_free (&Complex) ;
  431. return (GrB_SUCCESS) ;
  432. }