Project

General

Profile

Bug #9595 » 0001-Enhance-round-trip-testing-of-floats-in-Wt-Dbo.patch

Bruce Toll, 01/10/2022 12:22 PM

View differences:

test/dbo/DboTest.C
4 4
 * See the LICENSE file for terms of use.
5 5
 */
6 6
#include <boost/test/unit_test.hpp>
7
#include <boost/predef.h>
7 8

  
8 9
#include <Wt/Dbo/Dbo.h>
9 10
#include <Wt/Dbo/FixedSqlConnectionPool.h>
......
3384 3385
  }
3385 3386
}
3386 3387

  
3388
BOOST_AUTO_TEST_CASE( dbo_test46 )
3389
{
3390
// To be conservative, only run on x86 architecture due to byte-order dependencies
3391
// in converting hex_values to floating point
3392
#ifdef BOOST_ARCH_X86
3393
  // Check for issues, including loss of precision, with float values that should round-trip
3394
  // Test data adapted from:
3395
  // https://raw.githubusercontent.com/postgres/postgres/REL_12_9/src/test/regress/sql/float4.sql
3396
  // See license: https://raw.githubusercontent.com/postgres/postgres/REL_12_9/COPYRIGHT
3397
  DboFixture f;
3398

  
3399
  float quiet_nan = std::nanf("");
3400
  static const uint32_t quiet_nan_hex = *(reinterpret_cast<uint32_t*>(&quiet_nan));
3401

  
3402
  float positive_infinity = std::numeric_limits<float>::infinity();
3403
  static const uint32_t positive_infinity_hex = *(reinterpret_cast<uint32_t*>(&positive_infinity));
3404

  
3405
  float negative_infinity = -std::numeric_limits<float>::infinity();
3406
  static const uint32_t negative_infinity_hex = *(reinterpret_cast<uint32_t*>(&negative_infinity));
3407

  
3408
  static const uint32_t hex_values[] {
3409
    // some special values
3410
    quiet_nan_hex,
3411
    positive_infinity_hex,
3412
    negative_infinity_hex,
3413

  
3414
    // small subnormals
3415
    0x00000001,
3416
    0x00000002, 0x00000003,
3417
    0x00000010, 0x00000011, 0x00000100, 0x00000101,
3418
    0x00004000, 0x00004001, 0x00080000, 0x00080001,
3419

  
3420
    // stress values
3421
    0x0053c4f4,  // 7693e-42
3422
    0x006c85c4,  // 996622e-44
3423
    0x0041ca76,  // 60419369e-46
3424
    0x004b7678,  // 6930161142e-48
3425

  
3426
    // taken from upstream testsuite
3427
    0x00000007,
3428
    0x00424fe2,
3429

  
3430
    // borderline between subnormal and normal
3431
    0x007ffff0, 0x007ffff1, 0x007ffffe, 0x007fffff,
3432

  
3433
    // additional tests
3434
    0x00000000,
3435

  
3436
    // smallest normal values
3437
    0x00800000, 0x00800001, 0x00800004, 0x00800005,
3438
    0x00800006,
3439

  
3440
    // small normal values chosen for short vs. long output
3441
    0x008002f1, 0x008002f2, 0x008002f3,
3442
    0x00800e17, 0x00800e18, 0x00800e19,
3443

  
3444
    // assorted values (random mantissae)
3445
    0x01000001, 0x01102843, 0x01a52c98,
3446
    0x0219c229, 0x02e4464d, 0x037343c1, 0x03a91b36,
3447
    0x047ada65, 0x0496fe87, 0x0550844f, 0x05999da3,
3448
    0x060ea5e2, 0x06e63c45, 0x07f1e548, 0x0fc5282b,
3449
    0x1f850283, 0x2874a9d6,
3450

  
3451
    // values around 5e-08
3452
    0x3356bf94, 0x3356bf95, 0x3356bf96,
3453

  
3454
    // around 1e-07
3455
    0x33d6bf94, 0x33d6bf95, 0x33d6bf96,
3456

  
3457
    // around 3e-07 .. 1e-04
3458
    0x34a10faf, 0x34a10fb0, 0x34a10fb1,
3459
    0x350637bc, 0x350637bd, 0x350637be,
3460
    0x35719786, 0x35719787, 0x35719788,
3461
    0x358637bc, 0x358637bd, 0x358637be,
3462
    0x36a7c5ab, 0x36a7c5ac, 0x36a7c5ad,
3463
    0x3727c5ab, 0x3727c5ac, 0x3727c5ad,
3464

  
3465
    // format crossover at 1e-04
3466
    0x38d1b714, 0x38d1b715, 0x38d1b716,
3467
    0x38d1b717, 0x38d1b718, 0x38d1b719,
3468
    0x38d1b71a, 0x38d1b71b, 0x38d1b71c,
3469
    0x38d1b71d,
3470

  
3471
    0x38dffffe, 0x38dfffff, 0x38e00000,
3472
    0x38efffff, 0x38f00000, 0x38f00001,
3473
    0x3a83126e, 0x3a83126f, 0x3a831270,
3474
    0x3c23d709, 0x3c23d70a, 0x3c23d70b,
3475
    0x3dcccccc, 0x3dcccccd, 0x3dccccce,
3476

  
3477
    // chosen to need 9 digits for 3dcccd70
3478
    0x3dcccd6f, 0x3dcccd70, 0x3dcccd71,
3479

  
3480
    0x3effffff, 0x3f000000, 0x3f000001,
3481
    0x3f333332, 0x3f333333, 0x3f333334,
3482

  
3483
    // approach 1.0 with increasing numbers of 9s
3484
    0x3f666665, 0x3f666666, 0x3f666667,
3485
    0x3f7d70a3, 0x3f7d70a4, 0x3f7d70a5,
3486
    0x3f7fbe76, 0x3f7fbe77, 0x3f7fbe78,
3487
    0x3f7ff971, 0x3f7ff972, 0x3f7ff973,
3488
    0x3f7fff57, 0x3f7fff58, 0x3f7fff59,
3489
    0x3f7fffee, 0x3f7fffef,
3490

  
3491
    // values very close to 1
3492
    0x3f7ffff0, 0x3f7ffff1, 0x3f7ffff2,
3493
    0x3f7ffff3, 0x3f7ffff4, 0x3f7ffff5,
3494
    0x3f7ffff6, 0x3f7ffff7, 0x3f7ffff8,
3495
    0x3f7ffff9, 0x3f7ffffa, 0x3f7ffffb,
3496
    0x3f7ffffc, 0x3f7ffffd, 0x3f7ffffe,
3497
    0x3f7fffff,
3498
    0x3f800000,
3499
    0x3f800001, 0x3f800002, 0x3f800003,
3500
    0x3f800004, 0x3f800005, 0x3f800006,
3501
    0x3f800007, 0x3f800008, 0x3f800009,
3502

  
3503
    // values 1 to 1.1
3504
    0x3f80000f, 0x3f800010, 0x3f800011,
3505
    0x3f800012, 0x3f800013, 0x3f800014,
3506
    0x3f800017, 0x3f800018, 0x3f800019,
3507
    0x3f80001a, 0x3f80001b, 0x3f80001c,
3508
    0x3f800029, 0x3f80002a, 0x3f80002b,
3509
    0x3f800053, 0x3f800054, 0x3f800055,
3510
    0x3f800346, 0x3f800347, 0x3f800348,
3511
    0x3f8020c4, 0x3f8020c5, 0x3f8020c6,
3512
    0x3f8147ad, 0x3f8147ae, 0x3f8147af,
3513
    0x3f8ccccc, 0x3f8ccccd, 0x3f8cccce,
3514

  
3515
    0x3fc90fdb, // pi/2
3516
    0x402df854, // e
3517
    0x40490fdb, // pi
3518

  
3519
    0x409fffff, 0x40a00000, 0x40a00001,
3520
    0x40afffff, 0x40b00000, 0x40b00001,
3521
    0x411fffff, 0x41200000, 0x41200001,
3522
    0x42c7ffff, 0x42c80000, 0x42c80001,
3523
    0x4479ffff, 0x447a0000, 0x447a0001,
3524
    0x461c3fff, 0x461c4000, 0x461c4001,
3525
    0x47c34fff, 0x47c35000, 0x47c35001,
3526
    0x497423ff, 0x49742400, 0x49742401,
3527
    0x4b18967f, 0x4b189680, 0x4b189681,
3528
    0x4cbebc1f, 0x4cbebc20, 0x4cbebc21,
3529
    0x4e6e6b27, 0x4e6e6b28, 0x4e6e6b29,
3530
    0x501502f8, 0x501502f9, 0x501502fa,
3531
    0x51ba43b6, 0x51ba43b7, 0x51ba43b8,
3532

  
3533
    // stress values
3534
    0x1f6c1e4a,  // 5e-20
3535
    0x59be6cea,  // 67e14
3536
    0x5d5ab6c4,  // 985e15
3537
    0x2cc4a9bd,  // 55895e-16
3538
    0x15ae43fd,  // 7038531e-32
3539
    0x2cf757ca,  // 702990899e-20
3540
    0x665ba998,  // 25933168707e13
3541
    0x743c3324,  // 596428896559e20
3542

  
3543
    // exercise fixed-point memmoves
3544
    0x47f1205a,
3545
    0x4640e6ae,
3546
    0x449a5225,
3547
    0x42f6e9d5,
3548
    0x414587dd,
3549
    0x3f9e064b,
3550

  
3551
    // these cases come from the upstream's testsuite
3552
    // BoundaryRoundEven
3553
    0x4c000004,
3554
    0x50061c46,
3555
    0x510006a8,
3556

  
3557
    // ExactValueRoundEven
3558
    0x48951f84,
3559
    0x45fd1840,
3560

  
3561
    // LotsOfTrailingZeros
3562
    0x39800000,
3563
    0x3b200000,
3564
    0x3b900000,
3565
    0x3bd00000,
3566

  
3567
    // Regression
3568
    0x63800000,
3569
    0x4b000000,
3570
    0x4b800000,
3571
    0x4c000001,
3572
    0x4c800b0d,
3573
    0x00d24584,
3574
    0x00d90b88,
3575
    0x45803f34,
3576
    0x4f9f24f7,
3577
    0x3a8722c3,
3578
    0x5c800041,
3579
    0x15ae43fd,
3580
    0x5d4cccfb,
3581
    0x4c800001,
3582
    0x57800ed8,
3583
    0x5f000000,
3584
    0x700000f0,
3585
    0x5f23e9ac,
3586
    0x5e9502f9,
3587
    0x5e8012b1,
3588
    0x3c000028,
3589
    0x60cde861,
3590
    0x03aa2a50,
3591
    0x43480000,
3592
    0x4c000000,
3593

  
3594
    // LooksLikePow5
3595
    0x5D1502F9,
3596
    0x5D9502F9,
3597
    0x5E1502F9,
3598

  
3599
    // OutputLength
3600
    0x3f99999a,
3601
    0x3f9d70a4,
3602
    0x3f9df3b6,
3603
    0x3f9e0419,
3604
    0x3f9e0610,
3605
    0x3f9e064b,
3606
    0x3f9e0651,
3607
    0x03d20cfe
3608
  };
3609

  
3610
  for (int i = 0; i < sizeof hex_values / sizeof hex_values[0]; ++i) {
3611
    auto hex_value = hex_values[i];
3612
    float fl = *(reinterpret_cast<float*>(&hex_value));
3613
    char buf[100];
3614
    snprintf(buf, sizeof buf, "%.9g", fl);
3615
    BOOST_TEST_MESSAGE ("hex_value: " << std::hex << hex_value << std::dec << ", value: " << buf );
3616

  
3617
    float fl_from_database = 0.0f;
3618
    std::string exception_msg;
3619

  
3620
    try {
3621
      {
3622
        dbo::Transaction t(*f.session_);
3623
        auto a = f.session_->addNew<A>();
3624
        a.modify()->i = i;
3625
        a.modify()->f = fl;
3626
      }
3627

  
3628
#ifdef POSTGRES
3629
      {
3630
        dbo::Transaction t(*f.session_);
3631
        std::string fl_from_database_s = f.session_->query<std::string>(
3632
          "SELECT \"f\" FROM " SCHEMA "\"table_a\" WHERE \"i\"=?"
3633
        ).bind(i).resultValue();
3634
        BOOST_TEST_MESSAGE ("PG text value: " << fl_from_database_s );
3635
      }
3636
#endif
3637

  
3638
      {
3639
        dbo::Transaction t(*f.session_);
3640
        auto a = f.session_->find<A>().where("\"i\" = ?").bind(i).resultValue();
3641
        fl_from_database = a->f;
3642
      }
3643
    } catch (std::exception& e) {
3644
      exception_msg = std::string("unexpected exception: ") + e.what();
3645
    }
3646

  
3647
    BOOST_TEST(exception_msg.empty(), exception_msg);
3648
    if (exception_msg.empty()) {
3649
      if (std::isnan(fl)) {
3650
        BOOST_CHECK(std::isnan(fl_from_database));
3651
      }
3652
      else if (std::isinf(fl)) {
3653
        BOOST_CHECK(std::isinf(fl_from_database));
3654
        BOOST_CHECK_EQUAL(fl_from_database, fl);
3655
      }
3656
      else if (std::fpclassify(fl) == FP_SUBNORMAL) {
3657
        // kludge to improve warning (highlighting that it is a subnormal)
3658
        float subnormal_fl = fl;
3659
        BOOST_CHECK_CLOSE(fl_from_database, subnormal_fl, 1e-5);
3660
        // only warn if subnormals do not match, since implementations/support may vary
3661
        BOOST_WARN_EQUAL(fl_from_database, subnormal_fl);
3662
      }
3663
      else {
3664
        BOOST_CHECK_CLOSE(fl_from_database, fl, 1e-5);
3665
        BOOST_CHECK_EQUAL(fl_from_database, fl);
3666
      }
3667
    }
3668
  }
3669
#endif
3670
}
3671

  
3672
BOOST_AUTO_TEST_CASE( dbo_test47 )
3673
{
3674
// To be conservative, only run on x86 architecture due to byte-order dependencies
3675
// in converting hex_values to floating point
3676
#ifdef BOOST_ARCH_X86
3677
  // Check for issues, including loss of precision, with double values that should round-trip
3678
  // Test data adapted from:
3679
  // https://raw.githubusercontent.com/postgres/postgres/REL_12_9/src/test/regress/sql/float8.sql
3680
  // See license: https://raw.githubusercontent.com/postgres/postgres/REL_12_9/COPYRIGHT
3681
  DboFixture f;
3682

  
3683
  double quiet_nan = std::nan("");
3684
  static const uint64_t quiet_nan_hex = *(reinterpret_cast<uint64_t*>(&quiet_nan));
3685

  
3686
  double positive_infinity = std::numeric_limits<double>::infinity();
3687
  static const uint64_t positive_infinity_hex = *(reinterpret_cast<uint64_t*>(&positive_infinity));
3688

  
3689
  double negative_infinity = -std::numeric_limits<double>::infinity();
3690
  static const uint64_t negative_infinity_hex = *(reinterpret_cast<uint64_t*>(&negative_infinity));
3691

  
3692
  static const uint64_t hex_values[] {
3693
    // some special values
3694
    quiet_nan_hex,
3695
    positive_infinity_hex,
3696
    negative_infinity_hex,
3697

  
3698
    // small subnormals
3699
    0x0000000000000001,
3700
    0x0000000000000002, 0x0000000000000003,
3701
    0x0000000000001000, 0x0000000100000000,
3702
    0x0000010000000000, 0x0000010100000000,
3703
    0x0000400000000000, 0x0000400100000000,
3704
    0x0000800000000000, 0x0000800000000001,
3705

  
3706
    // these values taken from upstream testsuite
3707
    0x00000000000f4240,
3708
    0x00000000016e3600,
3709
    0x0000008cdcdea440,
3710

  
3711
    // borderline between subnormal and normal
3712
    0x000ffffffffffff0, 0x000ffffffffffff1,
3713
    0x000ffffffffffffe, 0x000fffffffffffff,
3714

  
3715
    // additional tests
3716
    0x0000000000000000,
3717

  
3718
    // smallest normal values
3719
    0x0010000000000000, 0x0010000000000001,
3720
    0x0010000000000002, 0x0018000000000000,
3721

  
3722
    0x3ddb7cdfd9d7bdba, 0x3ddb7cdfd9d7bdbb, 0x3ddb7cdfd9d7bdbc,
3723
    0x3e112e0be826d694, 0x3e112e0be826d695, 0x3e112e0be826d696,
3724
    0x3e45798ee2308c39, 0x3e45798ee2308c3a, 0x3e45798ee2308c3b,
3725
    0x3e7ad7f29abcaf47, 0x3e7ad7f29abcaf48, 0x3e7ad7f29abcaf49,
3726
    0x3eb0c6f7a0b5ed8c, 0x3eb0c6f7a0b5ed8d, 0x3eb0c6f7a0b5ed8e,
3727
    0x3ee4f8b588e368ef, 0x3ee4f8b588e368f0, 0x3ee4f8b588e368f1,
3728
    0x3f1a36e2eb1c432c, 0x3f1a36e2eb1c432d, 0x3f1a36e2eb1c432e,
3729
    0x3f50624dd2f1a9fb, 0x3f50624dd2f1a9fc, 0x3f50624dd2f1a9fd,
3730
    0x3f847ae147ae147a, 0x3f847ae147ae147b, 0x3f847ae147ae147c,
3731
    0x3fb9999999999999, 0x3fb999999999999a, 0x3fb999999999999b,
3732

  
3733
    // values very close to 1
3734
    0x3feffffffffffff0, 0x3feffffffffffff1, 0x3feffffffffffff2,
3735
    0x3feffffffffffff3, 0x3feffffffffffff4, 0x3feffffffffffff5,
3736
    0x3feffffffffffff6, 0x3feffffffffffff7, 0x3feffffffffffff8,
3737
    0x3feffffffffffff9, 0x3feffffffffffffa, 0x3feffffffffffffb,
3738
    0x3feffffffffffffc, 0x3feffffffffffffd, 0x3feffffffffffffe,
3739
    0x3fefffffffffffff,
3740
    0x3ff0000000000000,
3741
    0x3ff0000000000001, 0x3ff0000000000002, 0x3ff0000000000003,
3742
    0x3ff0000000000004, 0x3ff0000000000005, 0x3ff0000000000006,
3743
    0x3ff0000000000007, 0x3ff0000000000008, 0x3ff0000000000009,
3744

  
3745
    0x3ff921fb54442d18,
3746
    0x4005bf0a8b14576a,
3747
    0x400921fb54442d18,
3748

  
3749
    0x4023ffffffffffff, 0x4024000000000000, 0x4024000000000001,
3750
    0x4058ffffffffffff, 0x4059000000000000, 0x4059000000000001,
3751
    0x408f3fffffffffff, 0x408f400000000000, 0x408f400000000001,
3752
    0x40c387ffffffffff, 0x40c3880000000000, 0x40c3880000000001,
3753
    0x40f869ffffffffff, 0x40f86a0000000000, 0x40f86a0000000001,
3754
    0x412e847fffffffff, 0x412e848000000000, 0x412e848000000001,
3755
    0x416312cfffffffff, 0x416312d000000000, 0x416312d000000001,
3756
    0x4197d783ffffffff, 0x4197d78400000000, 0x4197d78400000001,
3757
    0x41cdcd64ffffffff, 0x41cdcd6500000000, 0x41cdcd6500000001,
3758
    0x4202a05f1fffffff, 0x4202a05f20000000, 0x4202a05f20000001,
3759
    0x42374876e7ffffff, 0x42374876e8000000, 0x42374876e8000001,
3760
    0x426d1a94a1ffffff, 0x426d1a94a2000000, 0x426d1a94a2000001,
3761
    0x42a2309ce53fffff, 0x42a2309ce5400000, 0x42a2309ce5400001,
3762
    0x42d6bcc41e8fffff, 0x42d6bcc41e900000, 0x42d6bcc41e900001,
3763
    0x430c6bf52633ffff, 0x430c6bf526340000, 0x430c6bf526340001,
3764
    0x4341c37937e07fff, 0x4341c37937e08000, 0x4341c37937e08001,
3765
    0x4376345785d89fff, 0x4376345785d8a000, 0x4376345785d8a001,
3766
    0x43abc16d674ec7ff, 0x43abc16d674ec800, 0x43abc16d674ec801,
3767
    0x43e158e460913cff, 0x43e158e460913d00, 0x43e158e460913d01,
3768
    0x4415af1d78b58c3f, 0x4415af1d78b58c40, 0x4415af1d78b58c41,
3769
    0x444b1ae4d6e2ef4f, 0x444b1ae4d6e2ef50, 0x444b1ae4d6e2ef51,
3770
    0x4480f0cf064dd591, 0x4480f0cf064dd592, 0x4480f0cf064dd593,
3771
    0x44b52d02c7e14af5, 0x44b52d02c7e14af6, 0x44b52d02c7e14af7,
3772
    0x44ea784379d99db3, 0x44ea784379d99db4, 0x44ea784379d99db5,
3773
    0x45208b2a2c280290, 0x45208b2a2c280291, 0x45208b2a2c280292,
3774

  
3775
    0x7feffffffffffffe, 0x7fefffffffffffff,
3776

  
3777
    // round to even tests (+ve)
3778
    0x4350000000000002,
3779
    0x4350000000002e06,
3780
    0x4352000000000003,
3781
    0x4352000000000004,
3782
    0x4358000000000003,
3783
    0x4358000000000004,
3784
    0x435f000000000020,
3785

  
3786
    // round to even tests (-ve)
3787
    0xc350000000000002,
3788
    0xc350000000002e06,
3789
    0xc352000000000003,
3790
    0xc352000000000004,
3791
    0xc358000000000003,
3792
    0xc358000000000004,
3793
    0xc35f000000000020,
3794

  
3795
    // exercise fixed-point memmoves
3796
    0x42dc12218377de66,
3797
    0x42a674e79c5fe51f,
3798
    0x4271f71fb04cb74c,
3799
    0x423cbe991a145879,
3800
    0x4206fee0e1a9e061,
3801
    0x41d26580b487e6b4,
3802
    0x419d6f34540ca453,
3803
    0x41678c29dcd6e9dc,
3804
    0x4132d687e3df217d,
3805
    0x40fe240c9fcb68c8,
3806
    0x40c81cd6e63c53d3,
3807
    0x40934a4584fd0fdc,
3808
    0x405edd3c07fb4c93,
3809
    0x4028b0fcd32f7076,
3810
    0x3ff3c0ca428c59f8,
3811

  
3812
    // these cases come from the upstream's testsuite
3813
    // LotsOfTrailingZeros)
3814
    0x3e60000000000000,
3815

  
3816
    // Regression
3817
    0xc352bd2668e077c4,
3818
    0x434018601510c000,
3819
    0x43d055dc36f24000,
3820
    0x43e052961c6f8000,
3821
    0x3ff3c0ca2a5b1d5d,
3822

  
3823
    // LooksLikePow5
3824
    0x4830f0cf064dd592,
3825
    0x4840f0cf064dd592,
3826
    0x4850f0cf064dd592,
3827

  
3828
    // OutputLength
3829
    0x3ff3333333333333,
3830
    0x3ff3ae147ae147ae,
3831
    0x3ff3be76c8b43958,
3832
    0x3ff3c083126e978d,
3833
    0x3ff3c0c1fc8f3238,
3834
    0x3ff3c0c9539b8887,
3835
    0x3ff3c0ca2a5b1d5d,
3836
    0x3ff3c0ca4283de1b,
3837
    0x3ff3c0ca43db770a,
3838
    0x3ff3c0ca428abd53,
3839
    0x3ff3c0ca428c1d2b,
3840
    0x3ff3c0ca428c51f2,
3841
    0x3ff3c0ca428c58fc,
3842
    0x3ff3c0ca428c59dd,
3843
    0x3ff3c0ca428c59f8,
3844
    0x3ff3c0ca428c59fb,
3845

  
3846
    // 32-bit chunking
3847
    0x40112e0be8047a7d,
3848
    0x40112e0be815a889,
3849
    0x40112e0be826d695,
3850
    0x40112e0be83804a1,
3851
    0x40112e0be84932ad,
3852

  
3853
    // MinMaxShift
3854
    0x0040000000000000,
3855
    0x007fffffffffffff,
3856
    0x0290000000000000,
3857
    0x029fffffffffffff,
3858
    0x4350000000000000,
3859
    0x435fffffffffffff,
3860
    0x1330000000000000,
3861
    0x133fffffffffffff,
3862
    0x3a6fa7161a4d6e0c
3863
  };
3864

  
3865
  for (int i = 0; i < sizeof hex_values / sizeof hex_values[0]; ++i) {
3866
    auto hex_value = hex_values[i];
3867
    double dbl = *(reinterpret_cast<double*>(&hex_value));
3868
    char buf[100];
3869
    snprintf(buf, sizeof buf, "%.17g", dbl);
3870
    BOOST_TEST_MESSAGE ("hex_value: " << std::hex << hex_value << std::dec << ", value: " << buf );
3871

  
3872
    double dbl_from_database = 0.0;
3873
    std::string exception_msg;
3874

  
3875
    try {
3876
      {
3877
        dbo::Transaction t(*f.session_);
3878
        auto a = f.session_->addNew<A>();
3879
        a.modify()->i = i;
3880
        a.modify()->d = dbl;
3881
      }
3882

  
3883
#ifdef POSTGRES
3884
      {
3885
        dbo::Transaction t(*f.session_);
3886
        std::string dbl_from_database_s = f.session_->query<std::string>(
3887
          "SELECT \"d\" FROM " SCHEMA "\"table_a\" WHERE \"i\"=?"
3888
        ).bind(i).resultValue();
3889
        BOOST_TEST_MESSAGE ("PG text value: " << dbl_from_database_s );
3890
      }
3891
#endif
3892

  
3893
      {
3894
        dbo::Transaction t(*f.session_);
3895
        auto a = f.session_->find<A>().where("\"i\" = ?").bind(i).resultValue();
3896
        dbl_from_database = a->d;
3897
      }
3898
    } catch (std::exception& e) {
3899
      exception_msg = std::string("unexpected exception: ") + e.what();
3900
    }
3901

  
3902
    BOOST_TEST(exception_msg.empty(), exception_msg);
3903
    if (exception_msg.empty()) {
3904
      if (std::isnan(dbl)) {
3905
        BOOST_CHECK(std::isnan(dbl_from_database));
3906
      }
3907
      else if (std::isinf(dbl)) {
3908
        BOOST_CHECK(std::isinf(dbl_from_database));
3909
        BOOST_CHECK_EQUAL(dbl_from_database, dbl);
3910
      }
3911
      else if (std::fpclassify(dbl) == FP_SUBNORMAL) {
3912
        // kludge to improve warning (highlighting that it is a subnormal)
3913
        double subnormal_dbl = dbl;
3914
        BOOST_CHECK_CLOSE(dbl_from_database, subnormal_dbl, 2e-14);
3915
        // only warn if subnormals do not match, since implementations/support may vary
3916
        BOOST_WARN_EQUAL(dbl_from_database, subnormal_dbl);
3917
      }
3918
      else {
3919
        BOOST_CHECK_CLOSE(dbl_from_database, dbl, 2e-14);
3920
        BOOST_CHECK_EQUAL(dbl_from_database, dbl);
3921
      }
3922
    }
3923
  }
3924
#endif
3925
}
3926

  
3387 3927
BOOST_AUTO_TEST_SUITE_END()
3388
- 
(1-1/2)