Distributions.cpp 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. /* Distributions.cpp
  2. *
  3. * Copyright (C) 1997-2012,2014,2015,2016,2017 Paul Boersma
  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.
  13. * See the GNU 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. #include "Distributions.h"
  19. Thing_implement (Distributions, TableOfReal, 0);
  20. void structDistributions :: v_info () {
  21. structDaata :: v_info ();
  22. MelderInfo_writeLine (U"Number of distributions: ", numberOfColumns);
  23. MelderInfo_writeLine (U"Number of values: ", numberOfRows);
  24. }
  25. autoDistributions Distributions_create (integer numberOfRows, integer numberOfColumns) {
  26. try {
  27. autoDistributions me = Thing_new (Distributions);
  28. TableOfReal_init (me.get(), numberOfRows, numberOfColumns);
  29. return me;
  30. } catch (MelderError) {
  31. Melder_throw (U"Distributions not created.");
  32. }
  33. }
  34. void Distributions_checkSpecifiedColumnNumberWithinRange (Distributions me, integer columnNumber) {
  35. if (columnNumber < 1)
  36. Melder_throw (me, U": the specified column number is ", columnNumber, U", but should be at least 1.");
  37. if (columnNumber > my numberOfColumns)
  38. Melder_throw (me, U": the specified column number is ", columnNumber, U", but should be at most my number of columns (", my numberOfColumns, U").");
  39. }
  40. void Distributions_peek (Distributions me, integer column, conststring32 *out_string, integer *out_number) {
  41. Distributions_checkSpecifiedColumnNumberWithinRange (me, column);
  42. if (my numberOfRows < 1)
  43. Melder_throw (me, U": I have no candidates.");
  44. longdouble total = 0.0;
  45. for (integer irow = 1; irow <= my numberOfRows; irow ++) {
  46. total += (longdouble) my data [irow] [column];
  47. }
  48. if (total <= 0.0)
  49. Melder_throw (me, U": the total weight of column ", column, U" is not positive.");
  50. integer irow;
  51. do {
  52. double rand = NUMrandomUniform (0, (double) total);
  53. longdouble sum = 0.0;
  54. for (irow = 1; irow <= my numberOfRows; irow ++) {
  55. sum += my data [irow] [column];
  56. if (rand <= sum) break;
  57. }
  58. } while (irow > my numberOfRows); // guard against rounding errors
  59. if (! my rowLabels [irow])
  60. Melder_throw (me, U": no string in row ", irow, U".");
  61. if (out_string)
  62. *out_string = my rowLabels [irow].get();
  63. if (out_number)
  64. *out_number = irow;
  65. }
  66. double Distributions_getProbability (Distributions me, conststring32 string, integer column) {
  67. integer row, rowOfString = 0;
  68. longdouble total = 0.0;
  69. if (column < 1 || column > my numberOfColumns) return undefined;
  70. for (row = 1; row <= my numberOfRows; row ++) {
  71. total += my data [row] [column];
  72. if (my rowLabels [row] && str32equ (my rowLabels [row].get(), string))
  73. rowOfString = row;
  74. }
  75. if (total <= 0.0) return undefined;
  76. if (rowOfString == 0) return 0.0;
  77. return my data [rowOfString] [column] / (double) total;
  78. }
  79. double Distributionses_getMeanAbsoluteDifference (Distributions me, Distributions thee, integer column) {
  80. if (column < 1 || column > my numberOfColumns || column > thy numberOfColumns ||
  81. my numberOfRows != thy numberOfRows) return undefined;
  82. longdouble total = 0.0;
  83. for (integer irow = 1; irow <= my numberOfRows; irow ++) {
  84. total += (longdouble) fabs (my data [irow] [column] - thy data [irow] [column]);
  85. }
  86. return (double) total / my numberOfRows;
  87. }
  88. static void unicize (Distributions me) {
  89. /* Must have been sorted beforehand. */
  90. integer nrow = 0, ifrom = 1;
  91. for (integer irow = 1; irow <= my numberOfRows; irow ++) {
  92. if (irow == my numberOfRows || !! my rowLabels [irow] != !! my rowLabels [irow + 1] ||
  93. my rowLabels [irow] && ! str32equ (my rowLabels [irow].get(), my rowLabels [irow + 1].get()))
  94. {
  95. /*
  96. Detected a change.
  97. */
  98. nrow ++;
  99. integer ito = irow;
  100. /*
  101. Move row 'ifrom' to 'nrow'. May be the same row.
  102. */
  103. if (ifrom != nrow) {
  104. my rowLabels [nrow] = my rowLabels [ifrom].move();
  105. for (integer icol = 1; icol <= my numberOfColumns; icol ++)
  106. my data [nrow] [icol] = my data [ifrom] [icol];
  107. }
  108. /*
  109. Purge rows from 'ifrom'+1 to 'ito'.
  110. */
  111. for (integer j = ifrom + 1; j <= ito; j ++) {
  112. my rowLabels [j]. reset();
  113. for (integer icol = 1; icol <= my numberOfColumns; icol ++)
  114. my data [nrow] [icol] += my data [j] [icol];
  115. }
  116. ifrom = ito + 1;
  117. }
  118. }
  119. my numberOfRows = nrow;
  120. }
  121. autoDistributions Distributions_addTwo (Distributions me, Distributions thee) {
  122. try {
  123. autoDistributions him = TablesOfReal_append (me, thee).static_cast_move<structDistributions>();
  124. TableOfReal_sortByLabel (him.get(), 0, 0);
  125. unicize (him.get());
  126. return him;
  127. } catch (MelderError) {
  128. Melder_throw (me, U" & ", thee, U": not added.");
  129. }
  130. }
  131. autoDistributions Distributions_addMany (OrderedOf<structDistributions>* me) {
  132. try {
  133. autoDistributions thee = TablesOfReal_appendMany ((OrderedOf<structTableOfReal>*) me).static_cast_move<structDistributions>(); // FIXME cast
  134. TableOfReal_sortByLabel (thee.get(), 0, 0);
  135. unicize (thee.get());
  136. return thee;
  137. } catch (MelderError) {
  138. Melder_throw (U"Distributions objects not added.");
  139. }
  140. }
  141. /* End of file Distributions.cpp */