106 line
2.6 KiB

  1. /*
  2. * libcucul Unicode canvas library
  3. * Copyright (c) 2002-2006 Sam Hocevar <sam@zoy.org>
  4. * All Rights Reserved
  5. *
  6. * This library is free software; you can redistribute it and/or
  7. * modify it under the terms of the Do What The Fuck You Want To
  8. * Public License, Version 2, as published by Sam Hocevar. See
  9. * http://sam.zoy.org/wtfpl/COPYING for more details.
  10. */
  11. /** \file math.c
  12. * \version \$Id$
  13. * \author Sam Hocevar <sam@zoy.org>
  14. * \brief Math
  15. *
  16. * This file contains simple mathematical routines.
  17. */
  18. #include "config.h"
  19. #if !defined(__KERNEL__)
  20. # include <stdlib.h>
  21. #endif
  22. #include "cucul.h"
  23. #include "cucul_internals.h"
  24. /**
  25. * \brief Generate a random integer within a range.
  26. *
  27. * \param min The lower bound of the integer range.
  28. * \param max The upper bound of the integer range.
  29. * \return A random integer comprised between \p min and \p max, inclusive.
  30. */
  31. int cucul_rand(int min, int max)
  32. {
  33. return min + (int)((1.0*(max-min+1)) * rand() / (RAND_MAX+1.0));
  34. }
  35. /**
  36. * \brief Approximate a square root, using Newton's method to avoid
  37. * costly floating point calculations.
  38. *
  39. * \param a A positive integer.
  40. * \return The approximate square root of \p a.
  41. */
  42. unsigned int cucul_sqrt(unsigned int a)
  43. {
  44. if(a == 0)
  45. return 0;
  46. if(a < 1000000000)
  47. {
  48. unsigned int x = a < 10 ? 1
  49. : a < 1000 ? 10
  50. : a < 100000 ? 100
  51. : a < 10000000 ? 1000
  52. : 10000;
  53. /* Newton's method. Three iterations would be more than enough. */
  54. x = (x * x + a) / x / 2;
  55. x = (x * x + a) / x / 2;
  56. x = (x * x + a) / x / 2;
  57. x = (x * x + a) / x / 2;
  58. return x;
  59. }
  60. return 2 * cucul_sqrt(a / 4);
  61. }
  62. /**
  63. * \brief powf substitute (x^y)
  64. * \param x The value to be raised
  65. * \param y The power to raise x to (only works with integers)
  66. * \return \p x raised to the power of \p y
  67. */
  68. float cucul_powf(float x, float y)
  69. {
  70. #ifdef __i386__
  71. /* FIXME: this can be optimised by directly calling fyl2x for x and y */
  72. register double logx;
  73. register long double v, e;
  74. asm volatile("fldln2; fxch; fyl2x"
  75. : "=t" (logx) : "0" (x) : "st(1)");
  76. asm volatile("fldl2e\n\t"
  77. "fmul %%st(1)\n\t"
  78. "fst %%st(1)\n\t"
  79. "frndint\n\t"
  80. "fxch\n\t"
  81. "fsub %%st(1)\n\t"
  82. "f2xm1\n\t"
  83. : "=t" (v), "=u" (e) : "0" (y * logx));
  84. v += 1.0;
  85. asm volatile("fscale"
  86. : "=t" (v) : "0" (v), "u" (e));
  87. return v;
  88. #else
  89. return x; /* HAHAHA VIEUX PORC */
  90. #endif
  91. }