1 /// Author: Aziz Köksal 2 /// License: GPL3 3 /// $(Maturity average) 4 module dil.Float; 5 6 import common; 7 8 // Used to be a wrapper class for the MPFR library functions. 9 // However, it was changed because the dependency has been a huge annoyance: 10 // * No up-to-date pre-compiled lib for Windows (let alone other platforms); 11 // * Can't be sure if the D mpfr struct has the correct size 12 13 /// A multiprecision float. TODO: needs to be implemented using BigInt. 14 /// Macros: 15 /// f = <a href="#Float.f" style="text-decoration:none">f</a> 16 class Float 17 { 18 real f; /// Implemented using a 'real' for now. 19 20 /// Constructs a Float initialized to NaN. 21 this() 22 { 23 } 24 25 /// Constructs from a Float. Copies x. 26 this(Float x) 27 { 28 f = x.f; 29 } 30 31 /// Constructs from a real. 32 this(real x) 33 { 34 f = x; 35 } 36 37 /// Constructs from an int. 38 this(int x) 39 { 40 this(cast(long)x); 41 } 42 43 /// Constructs from a uint. 44 this(uint x) 45 { 46 this(cast(ulong)x); 47 } 48 49 /// Constructs from a long. 50 this(long x) 51 { 52 f = x; 53 } 54 55 /// Constructs from a ulong. 56 this(ulong x) 57 { 58 f = x; 59 } 60 61 /// Constructs from a double. 62 this(double x) 63 { 64 f = x; 65 } 66 67 /// Constructs from a string. 68 this(cstring x, int base = 10) 69 { 70 if (!x.length) 71 this(); 72 else 73 { 74 if (x[$-1] != '\0') 75 x = x ~ '\0'; // Terminate with zero 76 this(x.ptr, base); 77 } 78 } 79 80 /// Constructs from a zero-terminated string. 81 this(cchar* x, int base = 10) 82 { 83 // TODO: 84 } 85 86 /// Constructs from a string and outputs a precision return code. 87 this(out int retcode, cstring str) 88 { 89 // TODO: 90 } 91 92 /// For convenient construction of Floats. 93 static Float opCall(Params...)(Params P) 94 { 95 return new Float(P); 96 } 97 98 /// Returns a deep copy of this number. 99 Float dup() 100 { 101 return new Float(this); 102 } 103 104 /// Returns true for an infinite number. 105 bool isInf() 106 { 107 // TODO: 108 return false; 109 } 110 111 /// Returns true for positive infinity. 112 bool isPInf() 113 { 114 // TODO: 115 return false; 116 } 117 118 /// Returns true for negative infinity. 119 bool isNInf() 120 { 121 // TODO: 122 return false; 123 } 124 125 /// Returns true for a NaN. 126 bool isNaN() 127 { 128 // TODO: 129 return false; 130 } 131 132 /// Returns true for zero. 133 bool isZero() 134 { 135 // TODO: 136 return false; 137 } 138 139 // TODO: add set() methods. 140 141 /// Calculates $(f) += x. 142 Float opAddAssign(Float x) 143 { 144 f += x.f; 145 return this; 146 } 147 148 /// Calculates $(f) += x. 149 Float opAddAssign(uint x) 150 { 151 f += x; 152 return this; 153 } 154 155 /// Calculates $(f) + x. 156 Float opAdd(T)(T x) 157 { 158 static if (is(T == Float) || is(T == uint)) 159 return dup() += x; 160 else 161 return dup() += new Float(x); 162 } 163 164 /// Calculates $(f) -= x. 165 Float opSubAssign(Float x) 166 { 167 f -= x.f; 168 return this; 169 } 170 171 /// Calculates $(f) -= x. 172 Float opSubAssign(uint x) 173 { 174 f -= x; 175 return this; 176 } 177 178 /// Calculates $(f) - x. 179 Float opSub(T)(T x) 180 { 181 static if (is(T == Float) || is(T == uint)) 182 return dup() -= x; 183 else 184 return dup() -= new Float(x); 185 } 186 187 /// Calculates x - $(f). 188 Float opSub_r(uint x) 189 { 190 return new Float(x - f); 191 } 192 193 /// Calculates $(f) /= x. 194 Float opDivAssign(Float x) 195 { 196 f /= x.f; 197 return this; 198 } 199 200 /// Calculates $(f) /= x. 201 Float opDivAssign(uint x) 202 { 203 f /= x; 204 return this; 205 } 206 207 /// Calculates $(f) / x. 208 Float opDiv(T)(T x) 209 { 210 static if (is(T == Float) || is(T == uint)) 211 return dup() /= x; 212 else 213 return dup() /= new Float(x); 214 } 215 216 /// Calculates x / $(f). 217 Float opDiv_r(uint x) 218 { 219 return new Float(x / f); 220 } 221 222 /// Calculates $(f) %= x. 223 Float opModAssign(Float x) 224 { 225 f %= x.f; 226 return this; 227 } 228 229 /// Calculates $(f) % x. 230 Float opMod(Float x) 231 { 232 return dup() %= x; 233 } 234 235 /// Calculates $(f) *= x. 236 Float opMulAssign(Float x) 237 { 238 f *= x.f; 239 return this; 240 } 241 242 /// Calculates $(f) *= x. 243 Float opMulAssign(uint x) 244 { 245 f *= x; 246 return this; 247 } 248 249 /// Calculates $(f) * x. 250 Float opMul(T)(T x) 251 { 252 static if (is(T == Float) || is(T == uint)) 253 return dup() *= x; 254 else 255 return dup() *= new Float(x); 256 } 257 258 /// Compares $(f) to x. 259 override bool opEquals(Object x) 260 { 261 if (auto y = cast(Float)x) 262 return opEquals(y); 263 return true; 264 } 265 266 /// Compares $(f) to x. 267 bool opEquals(Float x) 268 { 269 // TODO: 270 return false; 271 } 272 273 /// ditto 274 bool opEquals(double x) 275 { 276 // TODO: 277 return false; 278 } 279 280 /// ditto 281 bool opEquals(int x) 282 { 283 // TODO: 284 return false; 285 } 286 287 /// ditto 288 bool opEquals(uint x) 289 { 290 // TODO: 291 return false; 292 } 293 294 alias equals = opEquals; 295 296 alias opCmp = super.opCmp; 297 298 /// Compares $(f) to x. 299 int opCmp(Float x) 300 { 301 // TODO: 302 return false; 303 } 304 305 /// ditto 306 int opCmp(double x) 307 { 308 // TODO: 309 return false; 310 } 311 312 /// ditto 313 int opCmp(int x) 314 { 315 // TODO: 316 return false; 317 } 318 319 /// ditto 320 int opCmp(uint x) 321 { 322 // TODO: 323 return false; 324 } 325 326 /// Returns true if the first bits of $(f) and x are equal. 327 bool equals(Float x, uint bits) 328 { 329 // TODO: 330 return false; 331 } 332 333 /// Sets $(f) to frac($(f)). Returns itself. 334 Float fraction() 335 { 336 // TODO: 337 return this; 338 } 339 340 /// Returns a negated copy of this number. 341 Float opNeg() 342 { 343 auto x = dup(); 344 x.f = -f; 345 return x; 346 } 347 348 /// Negates this number. 349 Float neg() 350 { 351 f = -f; 352 return this; 353 } 354 355 /// Returns true if negative. 356 bool isNeg() 357 { 358 return f < 0; 359 } 360 361 /// Sets the number to its absolute value. Returns itself. 362 Float abs() 363 { 364 if (f < 0) 365 f = -f; 366 return this; 367 } 368 369 /// Returns this float as a string. 370 override string toString() 371 { 372 return toString(30).idup; 373 } 374 375 /// Returns this float as a string. 376 /// Formatted in the scientific representation. 377 char[] toString(uint precision) 378 { 379 // FIXME: 380 return Format("{}", f); 381 } 382 383 /// Returns the internals of the data structure as a hex string. 384 char[] toHex() 385 { 386 // FIXME: 387 return Format("{:X}", f); 388 } 389 390 // Exponentiation and logarithmic functions. 391 392 /// Calculates √$(f). Returns itself. 393 Float sqrt() 394 { 395 // TOOD: 396 return this; 397 } 398 399 /// Calculates √x. Returns a new Float. 400 static Float sqrt(uint x) 401 { 402 // TODO: 403 return new Float(); 404 } 405 406 /// Calculates $(f)$(SUP x). Returns itself. 407 Float pow(uint x) 408 { 409 // TODO: 410 return this; 411 } 412 413 /// Calculates $(f)². Returns itself. 414 Float square() 415 { 416 // TODO: 417 return this; 418 } 419 420 /// Calculates ln(x). Returns itself. 421 Float ln() 422 { 423 // TODO: 424 return this; 425 } 426 /// Calculates log$(SUB 2)(x). Returns itself. 427 Float log2() 428 { 429 // TODO: 430 return this; 431 } 432 /// Calculates log$(SUB 10)(x). Returns itself. 433 Float log10() 434 { 435 // TODO: 436 return this; 437 } 438 /// Calculates e$(SUP x). Returns itself. 439 Float exp() 440 { 441 // TODO: 442 return this; 443 } 444 445 /// Calculates acos(x). Returns itself. 446 Float acos() 447 { 448 // TODO: 449 return this; 450 } 451 452 /// Calculates asin(x). Returns itself. 453 Float asin() 454 { 455 // TODO: 456 return this; 457 } 458 459 /// Calculates atan(x). Returns itself. 460 Float atan() 461 { 462 // TODO: 463 return this; 464 } 465 466 /// Calculates sin(x). Returns itself. 467 Float sin() 468 { 469 // TODO: 470 return this; 471 } 472 473 /// Calculates cos(x). Returns itself. 474 Float cos() 475 { 476 // TODO: 477 return this; 478 } 479 480 /// Calculates tan(x). Returns itself. 481 Float tan() 482 { 483 // TODO: 484 return this; 485 } 486 487 /// Calculates atan(y/x). Returns itself. 488 Float atan2(Float x) 489 { 490 // TODO: 491 return this; 492 } 493 494 /// Calculates hypot(x, y) = √(x² + y²). Returns itself. 495 Float hypot(Float y) 496 { 497 // TODO: 498 return this; 499 } 500 } 501 502 /// Returns ln(x). 503 Float ln(Float x) 504 { 505 return x.dup().ln(); 506 } 507 /// Returns log$(SUB 2)(x). 508 Float log2(Float x) 509 { 510 return x.dup().log2(); 511 } 512 /// Returns log$(SUB 10)(x). 513 Float log10(Float x) 514 { 515 return x.dup().log10(); 516 } 517 /// Returns e$(SUP x). 518 Float exp(Float x) 519 { 520 return x.dup().exp(); 521 } 522 523 /// Returns acos(x). 524 Float acos(Float x) 525 { 526 return x.dup().acos(); 527 } 528 /// Returns asin(x). 529 Float asin(Float x) 530 { 531 return x.dup().asin(); 532 } 533 /// Returns atan(x). 534 Float atan(Float x) 535 { 536 return x.dup().atan(); 537 } 538 /// Returns sin(x). 539 Float sin(Float x) 540 { 541 return x.dup().sin(); 542 } 543 /// Returns cos(x). 544 Float cos(Float x) 545 { 546 return x.dup().cos(); 547 } 548 /// Returns tan(x). 549 Float tan(Float x) 550 { 551 return x.dup().tan(); 552 } 553 /// Returns atan2(x,y) = atan(y/x). 554 Float atan2(Float y, Float x) 555 { 556 return y.dup().atan2(x); 557 } 558 /// Returns hypot(x) = √(x² + y²). 559 Float hypot(Float x, Float y) 560 { 561 return x.dup().hypot(y); 562 } 563 564 565 void testFloat() 566 { 567 return; // Remove when Float is fixed. 568 scope msg = new UnittestMsg("Testing class Float."); 569 570 alias F = Float; 571 572 assert(F() == 0); 573 assert(F("").toString() == "0"); 574 assert(F("0").toString() == "0"); 575 assert(F("1.125").toString() == "1.125"); 576 577 size_t i = "123456789".length, 578 n = 1; 579 for (; i < i.max; (i--), (n *= 10)) 580 // E.g.: F("12345678.9") == F(123456789) / 10 581 assert(F("123456789"[0..i] ~ "." ~ "123456789"[i..$]) == F(123456789) / n); 582 583 assert(F("12345678.9") == F(123456789.0) / 10); 584 assert(F("12345678.9") == F(Format("{}", 12345678.9))); 585 assert(2 / F(0.5) == 4); 586 assert(F(0.5) / 2 == 0.25); 587 assert(F(0.5) * 8 == 4); 588 assert(F(1.2).dup() == F(1.2)); 589 assert(F(3.7) < F(3.8)); 590 assert(F(99.8) <= F(99.8)); 591 assert((F(39) += 61) == F(250e-1) * 4); 592 assert((F(100) /= 5) == (F(50e-1) *= 4)); 593 assert((F(111) -= 11) == F(111) - 11); 594 assert(10-F("3.5") == 6.5); 595 assert(10/F("2.5") == 4); 596 assert(F(2401).sqrt() == F(7).pow(2)); 597 assert(F(16).neg() == F(-16)); 598 assert(F(16).neg().abs() == F(-16).abs()); 599 assert(F(1).exp().ln() <= F(1)); 600 assert(F(32).square() == F(1024)); 601 } 602