Distance.cpp 2.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  1. /* Distance.cpp
  2. *
  3. * Copyright (C) 1993-2018 David Weenink
  4. *
  5. * This code is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation; either version 2 of the License, or (at
  8. * your option) any later version.
  9. *
  10. * This code is distributed in the hope that it will be useful, but
  11. * WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  13. * General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with this work. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. /*
  19. djmw 20020813 GPL header
  20. djmw 20110304 Thing_new
  21. */
  22. #include "Distance.h"
  23. #include "TableOfReal_extensions.h"
  24. Thing_implement (Distance, Proximity, 0);
  25. autoDistance Distance_create (integer numberOfPoints) {
  26. try {
  27. autoDistance me = Thing_new (Distance);
  28. Proximity_init (me.get(), numberOfPoints);
  29. return me;
  30. } catch (MelderError) {
  31. Melder_throw (U"Distance not created.");
  32. }
  33. }
  34. double Distance_getMaximumDistance (Distance me) {
  35. double dmax = 0.0;
  36. for (integer i = 1; i <= my numberOfRows; i ++) { // symmetric matrix
  37. for (integer j = i + 1; j <= my numberOfColumns; j ++) {
  38. if (my data [i] [j] > dmax) {
  39. dmax = my data [i] [j];
  40. }
  41. }
  42. }
  43. return dmax;
  44. }
  45. autoDistance Configuration_to_Distance (Configuration me) {
  46. try {
  47. autoDistance thee = Distance_create (my numberOfRows);
  48. TableOfReal_copyLabels (me, thee.get(), 1, -1);
  49. for (integer i = 1; i <= thy numberOfRows - 1; i ++) {
  50. for (integer j = i + 1; j <= thy numberOfColumns; j ++) {
  51. /*
  52. first divide distance by maximum to prevent overflow when metric is a large number.
  53. d = (x^n)^(1/n) may overflow if x>1 & n >>1 even if d would not overflow!
  54. metric changed 24/11/97
  55. my w [k] * pow (|i-j|) instead of pow (my w [k] * |i-j|)
  56. */
  57. double dmax = 0.0;
  58. for (integer k = 1; k <= my numberOfColumns; k ++) {
  59. double dtmp = fabs (my data [i] [k] - my data [j] [k]);
  60. if (dtmp > dmax) dmax = dtmp;
  61. }
  62. longdouble d = 0.0;
  63. if (dmax > 0.0) {
  64. for (integer k = 1; k <= my numberOfColumns; k ++) {
  65. double arg = fabs (my data [i] [k] - my data [j] [k]) / dmax;
  66. d += my w [k] * pow (arg, my metric);
  67. }
  68. }
  69. thy data [i] [j] = thy data [j] [i] = dmax * pow ((double) d, 1.0 / my metric);
  70. }
  71. }
  72. return thee;
  73. } catch (MelderError) {
  74. Melder_throw (me, U": no Distance created.");
  75. }
  76. }
  77. void Distance_drawDendogram (Distance me, Graphics g, int method) {
  78. (void) me;
  79. (void) g;
  80. (void) method;
  81. }
  82. /* End of file Distance.cpp */