go-type-complex.c 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. /* go-type-complex.c -- hash and equality complex functions.
  2. Copyright 2012 The Go Authors. All rights reserved.
  3. Use of this source code is governed by a BSD-style
  4. license that can be found in the LICENSE file. */
  5. #include <complex.h>
  6. #include <math.h>
  7. #include <stdint.h>
  8. #include <string.h>
  9. #include "runtime.h"
  10. #include "go-type.h"
  11. /* Hash function for float types. */
  12. uintptr_t
  13. __go_type_hash_complex (const void *vkey, uintptr_t key_size)
  14. {
  15. if (key_size == 8)
  16. {
  17. const complex float *cfp;
  18. complex float cf;
  19. float cfr;
  20. float cfi;
  21. uint64_t fi;
  22. cfp = (const complex float *) vkey;
  23. cf = *cfp;
  24. cfr = crealf (cf);
  25. cfi = cimagf (cf);
  26. if (isinf (cfr) || isinf (cfi))
  27. return 0;
  28. /* NaN != NaN, so the hash code of a NaN is irrelevant. Make it
  29. random so that not all NaNs wind up in the same place. */
  30. if (isnan (cfr) || isnan (cfi))
  31. return runtime_fastrand1 ();
  32. /* Avoid negative zero. */
  33. if (cfr == 0 && cfi == 0)
  34. return 0;
  35. else if (cfr == 0)
  36. cf = cfi * I;
  37. else if (cfi == 0)
  38. cf = cfr;
  39. memcpy (&fi, &cf, 8);
  40. return (uintptr_t) cfi;
  41. }
  42. else if (key_size == 16)
  43. {
  44. const complex double *cdp;
  45. complex double cd;
  46. double cdr;
  47. double cdi;
  48. uint64_t di[2];
  49. cdp = (const complex double *) vkey;
  50. cd = *cdp;
  51. cdr = creal (cd);
  52. cdi = cimag (cd);
  53. if (isinf (cdr) || isinf (cdi))
  54. return 0;
  55. if (isnan (cdr) || isnan (cdi))
  56. return runtime_fastrand1 ();
  57. /* Avoid negative zero. */
  58. if (cdr == 0 && cdi == 0)
  59. return 0;
  60. else if (cdr == 0)
  61. cd = cdi * I;
  62. else if (cdi == 0)
  63. cd = cdr;
  64. memcpy (&di, &cd, 16);
  65. return di[0] ^ di[1];
  66. }
  67. else
  68. runtime_throw ("__go_type_hash_complex: invalid complex size");
  69. }
  70. /* Equality function for complex types. */
  71. _Bool
  72. __go_type_equal_complex (const void *vk1, const void *vk2, uintptr_t key_size)
  73. {
  74. if (key_size == 8)
  75. {
  76. const complex float *cfp1;
  77. const complex float *cfp2;
  78. cfp1 = (const complex float *) vk1;
  79. cfp2 = (const complex float *) vk2;
  80. return *cfp1 == *cfp2;
  81. }
  82. else if (key_size == 16)
  83. {
  84. const complex double *cdp1;
  85. const complex double *cdp2;
  86. cdp1 = (const complex double *) vk1;
  87. cdp2 = (const complex double *) vk2;
  88. return *cdp1 == *cdp2;
  89. }
  90. else
  91. runtime_throw ("__go_type_equal_complex: invalid complex size");
  92. }