os/ossrv/stdcpp/tsrc/Boost_test/math/quaternion/inc/HSO3.hpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
sl@0
     1
sl@0
     2
/********************************************************************************************/
sl@0
     3
/*                                                                                          */
sl@0
     4
/*                                HSO3.hpp header file                                      */
sl@0
     5
/*                                                                                          */
sl@0
     6
/* This file is not currently part of the Boost library. It is simply an example of the use */
sl@0
     7
/* quaternions can be put to. Hopefully it will be useful too.                              */
sl@0
     8
/*                                                                                          */
sl@0
     9
/* This file provides tools to convert between quaternions and R^3 rotation matrices.       */
sl@0
    10
/*                                                                                          */
sl@0
    11
/********************************************************************************************/
sl@0
    12
sl@0
    13
//  (C) Copyright Hubert Holin 2001.
sl@0
    14
//  Distributed under the Boost Software License, Version 1.0. (See
sl@0
    15
//  accompanying file LICENSE_1_0.txt or copy at
sl@0
    16
//  http://www.boost.org/LICENSE_1_0.txt)
sl@0
    17
sl@0
    18
#ifndef TEST_HSO3_HPP
sl@0
    19
#define TEST_HSO3_HPP
sl@0
    20
sl@0
    21
#include <algorithm>
sl@0
    22
sl@0
    23
#if    defined(__GNUC__) && (__GNUC__ < 3)
sl@0
    24
#include <boost/limits.hpp>
sl@0
    25
#else
sl@0
    26
#include <limits>
sl@0
    27
#endif
sl@0
    28
sl@0
    29
#include <stdexcept>
sl@0
    30
#include <string>
sl@0
    31
sl@0
    32
#include <boost/math/quaternion.hpp>
sl@0
    33
sl@0
    34
sl@0
    35
#if    defined(__GNUC__) && (__GNUC__ < 3)
sl@0
    36
// gcc 2.x ignores function scope using declarations, put them here instead:
sl@0
    37
using    namespace ::std;
sl@0
    38
using    namespace ::boost::math;
sl@0
    39
#endif
sl@0
    40
sl@0
    41
template<typename TYPE_FLOAT>
sl@0
    42
struct  R3_matrix
sl@0
    43
{
sl@0
    44
    TYPE_FLOAT a11, a12, a13;
sl@0
    45
    TYPE_FLOAT a21, a22, a23;
sl@0
    46
    TYPE_FLOAT a31, a32, a33;
sl@0
    47
};
sl@0
    48
sl@0
    49
sl@0
    50
// Note:    the input quaternion need not be of norm 1 for the following function
sl@0
    51
sl@0
    52
template<typename TYPE_FLOAT>
sl@0
    53
R3_matrix<TYPE_FLOAT>    quaternion_to_R3_rotation(::boost::math::quaternion<TYPE_FLOAT> const & q)
sl@0
    54
{
sl@0
    55
    using    ::std::numeric_limits;
sl@0
    56
    
sl@0
    57
    TYPE_FLOAT    a = q.R_component_1();
sl@0
    58
    TYPE_FLOAT    b = q.R_component_2();
sl@0
    59
    TYPE_FLOAT    c = q.R_component_3();
sl@0
    60
    TYPE_FLOAT    d = q.R_component_4();
sl@0
    61
    
sl@0
    62
    TYPE_FLOAT    aa = a*a;
sl@0
    63
    TYPE_FLOAT    ab = a*b;
sl@0
    64
    TYPE_FLOAT    ac = a*c;
sl@0
    65
    TYPE_FLOAT    ad = a*d;
sl@0
    66
    TYPE_FLOAT    bb = b*b;
sl@0
    67
    TYPE_FLOAT    bc = b*c;
sl@0
    68
    TYPE_FLOAT    bd = b*d;
sl@0
    69
    TYPE_FLOAT    cc = c*c;
sl@0
    70
    TYPE_FLOAT    cd = c*d;
sl@0
    71
    TYPE_FLOAT    dd = d*d;
sl@0
    72
    
sl@0
    73
    TYPE_FLOAT    norme_carre = aa+bb+cc+dd;
sl@0
    74
    
sl@0
    75
    if    (norme_carre <= numeric_limits<TYPE_FLOAT>::epsilon())
sl@0
    76
    {
sl@0
    77
        ::std::string            error_reporting("Argument to quaternion_to_R3_rotation is too small!");
sl@0
    78
        ::std::underflow_error   bad_argument(error_reporting);
sl@0
    79
        
sl@0
    80
        throw(bad_argument);
sl@0
    81
    }
sl@0
    82
    
sl@0
    83
    R3_matrix<TYPE_FLOAT>    out_matrix;
sl@0
    84
    
sl@0
    85
    out_matrix.a11 = (aa+bb-cc-dd)/norme_carre;
sl@0
    86
    out_matrix.a12 = 2*(-ad+bc)/norme_carre;
sl@0
    87
    out_matrix.a13 = 2*(ac+bd)/norme_carre;
sl@0
    88
    out_matrix.a21 = 2*(ad+bc)/norme_carre;
sl@0
    89
    out_matrix.a22 = (aa-bb+cc-dd)/norme_carre;
sl@0
    90
    out_matrix.a23 = 2*(-ab+cd)/norme_carre;
sl@0
    91
    out_matrix.a31 = 2*(-ac+bd)/norme_carre;
sl@0
    92
    out_matrix.a32 = 2*(ab+cd)/norme_carre;
sl@0
    93
    out_matrix.a33 = (aa-bb-cc+dd)/norme_carre;
sl@0
    94
    
sl@0
    95
    return(out_matrix);
sl@0
    96
}
sl@0
    97
sl@0
    98
sl@0
    99
    template<typename TYPE_FLOAT>
sl@0
   100
    void    find_invariant_vector(  R3_matrix<TYPE_FLOAT> const & rot,
sl@0
   101
                                    TYPE_FLOAT & x,
sl@0
   102
                                    TYPE_FLOAT & y,
sl@0
   103
                                    TYPE_FLOAT & z)
sl@0
   104
    {
sl@0
   105
        using    ::std::sqrt;
sl@0
   106
        
sl@0
   107
        using    ::std::numeric_limits;
sl@0
   108
        
sl@0
   109
        TYPE_FLOAT    b11 = rot.a11 - static_cast<TYPE_FLOAT>(1);
sl@0
   110
        TYPE_FLOAT    b12 = rot.a12;
sl@0
   111
        TYPE_FLOAT    b13 = rot.a13;
sl@0
   112
        TYPE_FLOAT    b21 = rot.a21;
sl@0
   113
        TYPE_FLOAT    b22 = rot.a22 - static_cast<TYPE_FLOAT>(1);
sl@0
   114
        TYPE_FLOAT    b23 = rot.a23;
sl@0
   115
        TYPE_FLOAT    b31 = rot.a31;
sl@0
   116
        TYPE_FLOAT    b32 = rot.a32;
sl@0
   117
        TYPE_FLOAT    b33 = rot.a33 - static_cast<TYPE_FLOAT>(1);
sl@0
   118
        
sl@0
   119
        TYPE_FLOAT    minors[9] =
sl@0
   120
        {
sl@0
   121
            b11*b22-b12*b21,
sl@0
   122
            b11*b23-b13*b21,
sl@0
   123
            b12*b23-b13*b22,
sl@0
   124
            b11*b32-b12*b31,
sl@0
   125
            b11*b33-b13*b31,
sl@0
   126
            b12*b33-b13*b32,
sl@0
   127
            b21*b32-b22*b31,
sl@0
   128
            b21*b33-b23*b31,
sl@0
   129
            b22*b33-b23*b32
sl@0
   130
        };
sl@0
   131
        
sl@0
   132
        TYPE_FLOAT *        where = ::std::max_element(minors, minors+9);
sl@0
   133
        
sl@0
   134
        TYPE_FLOAT          det = *where;
sl@0
   135
        
sl@0
   136
        if    (det <= numeric_limits<TYPE_FLOAT>::epsilon())
sl@0
   137
        {
sl@0
   138
            ::std::string            error_reporting("Underflow error in find_invariant_vector!");
sl@0
   139
            ::std::underflow_error   processing_error(error_reporting);
sl@0
   140
            
sl@0
   141
            throw(processing_error);
sl@0
   142
        }
sl@0
   143
        
sl@0
   144
        switch    (where-minors)
sl@0
   145
        {
sl@0
   146
            case 0:
sl@0
   147
                
sl@0
   148
                z = static_cast<TYPE_FLOAT>(1);
sl@0
   149
                
sl@0
   150
                x = (-b13*b22+b12*b23)/det;
sl@0
   151
                y = (-b11*b23+b13*b21)/det;
sl@0
   152
                
sl@0
   153
                break;
sl@0
   154
                
sl@0
   155
            case 1:
sl@0
   156
                
sl@0
   157
                y = static_cast<TYPE_FLOAT>(1);
sl@0
   158
                
sl@0
   159
                x = (-b12*b23+b13*b22)/det;
sl@0
   160
                z = (-b11*b22+b12*b21)/det;
sl@0
   161
                
sl@0
   162
                break;
sl@0
   163
                
sl@0
   164
            case 2:
sl@0
   165
                
sl@0
   166
                x = static_cast<TYPE_FLOAT>(1);
sl@0
   167
                
sl@0
   168
                y = (-b11*b23+b13*b21)/det;
sl@0
   169
                z = (-b12*b21+b11*b22)/det;
sl@0
   170
                
sl@0
   171
                break;
sl@0
   172
                
sl@0
   173
            case 3:
sl@0
   174
                
sl@0
   175
                z = static_cast<TYPE_FLOAT>(1);
sl@0
   176
                
sl@0
   177
                x = (-b13*b32+b12*b33)/det;
sl@0
   178
                y = (-b11*b33+b13*b31)/det;
sl@0
   179
                
sl@0
   180
                break;
sl@0
   181
                
sl@0
   182
            case 4:
sl@0
   183
                
sl@0
   184
                y = static_cast<TYPE_FLOAT>(1);
sl@0
   185
                
sl@0
   186
                x = (-b12*b33+b13*b32)/det;
sl@0
   187
                z = (-b11*b32+b12*b31)/det;
sl@0
   188
                
sl@0
   189
                break;
sl@0
   190
                
sl@0
   191
            case 5:
sl@0
   192
                
sl@0
   193
                x = static_cast<TYPE_FLOAT>(1);
sl@0
   194
                
sl@0
   195
                y = (-b11*b33+b13*b31)/det;
sl@0
   196
                z = (-b12*b31+b11*b32)/det;
sl@0
   197
                
sl@0
   198
                break;
sl@0
   199
                
sl@0
   200
            case 6:
sl@0
   201
                
sl@0
   202
                z = static_cast<TYPE_FLOAT>(1);
sl@0
   203
                
sl@0
   204
                x = (-b23*b32+b22*b33)/det;
sl@0
   205
                y = (-b21*b33+b23*b31)/det;
sl@0
   206
                
sl@0
   207
                break;
sl@0
   208
                
sl@0
   209
            case 7:
sl@0
   210
                
sl@0
   211
                y = static_cast<TYPE_FLOAT>(1);
sl@0
   212
                
sl@0
   213
                x = (-b22*b33+b23*b32)/det;
sl@0
   214
                z = (-b21*b32+b22*b31)/det;
sl@0
   215
                
sl@0
   216
                break;
sl@0
   217
                
sl@0
   218
            case 8:
sl@0
   219
                
sl@0
   220
                x = static_cast<TYPE_FLOAT>(1);
sl@0
   221
                
sl@0
   222
                y = (-b21*b33+b23*b31)/det;
sl@0
   223
                z = (-b22*b31+b21*b32)/det;
sl@0
   224
                
sl@0
   225
                break;
sl@0
   226
                
sl@0
   227
            default:
sl@0
   228
                
sl@0
   229
                ::std::string        error_reporting("Impossible condition in find_invariant_vector");
sl@0
   230
                ::std::logic_error   processing_error(error_reporting);
sl@0
   231
                
sl@0
   232
                throw(processing_error);
sl@0
   233
                
sl@0
   234
                break;
sl@0
   235
        }
sl@0
   236
        
sl@0
   237
        TYPE_FLOAT    vecnorm = sqrt(x*x+y*y+z*z);
sl@0
   238
        
sl@0
   239
        if    (vecnorm <= numeric_limits<TYPE_FLOAT>::epsilon())
sl@0
   240
        {
sl@0
   241
            ::std::string            error_reporting("Overflow error in find_invariant_vector!");
sl@0
   242
            ::std::overflow_error    processing_error(error_reporting);
sl@0
   243
            
sl@0
   244
            throw(processing_error);
sl@0
   245
        }
sl@0
   246
        
sl@0
   247
        x /= vecnorm;
sl@0
   248
        y /= vecnorm;
sl@0
   249
        z /= vecnorm;
sl@0
   250
    }
sl@0
   251
    
sl@0
   252
    
sl@0
   253
    template<typename TYPE_FLOAT>
sl@0
   254
    void    find_orthogonal_vector( TYPE_FLOAT x,
sl@0
   255
                                    TYPE_FLOAT y,
sl@0
   256
                                    TYPE_FLOAT z,
sl@0
   257
                                    TYPE_FLOAT & u,
sl@0
   258
                                    TYPE_FLOAT & v,
sl@0
   259
                                    TYPE_FLOAT & w)
sl@0
   260
    {
sl@0
   261
        using    ::std::abs;
sl@0
   262
        using    ::std::sqrt;
sl@0
   263
        
sl@0
   264
        using    ::std::numeric_limits;
sl@0
   265
        
sl@0
   266
        TYPE_FLOAT    vecnormsqr = x*x+y*y+z*z;
sl@0
   267
        
sl@0
   268
        if    (vecnormsqr <= numeric_limits<TYPE_FLOAT>::epsilon())
sl@0
   269
        {
sl@0
   270
            ::std::string            error_reporting("Underflow error in find_orthogonal_vector!");
sl@0
   271
            ::std::underflow_error   processing_error(error_reporting);
sl@0
   272
            
sl@0
   273
            throw(processing_error);
sl@0
   274
        }
sl@0
   275
        
sl@0
   276
        TYPE_FLOAT        lambda;
sl@0
   277
        
sl@0
   278
        TYPE_FLOAT        components[3] =
sl@0
   279
        {
sl@0
   280
            abs(x),
sl@0
   281
            abs(y),
sl@0
   282
            abs(z)
sl@0
   283
        };
sl@0
   284
        
sl@0
   285
        TYPE_FLOAT *    where = ::std::min_element(components, components+3);
sl@0
   286
        
sl@0
   287
        switch    (where-components)
sl@0
   288
        {
sl@0
   289
            case 0:
sl@0
   290
                
sl@0
   291
                if    (*where <= numeric_limits<TYPE_FLOAT>::epsilon())
sl@0
   292
                {
sl@0
   293
                    v =
sl@0
   294
                    w = static_cast<TYPE_FLOAT>(0);
sl@0
   295
                    u = static_cast<TYPE_FLOAT>(1);
sl@0
   296
                }
sl@0
   297
                else
sl@0
   298
                {
sl@0
   299
                    lambda = -x/vecnormsqr;
sl@0
   300
                    
sl@0
   301
                    u = static_cast<TYPE_FLOAT>(1) + lambda*x;
sl@0
   302
                    v = lambda*y;
sl@0
   303
                    w = lambda*z;
sl@0
   304
                }
sl@0
   305
                
sl@0
   306
                break;
sl@0
   307
                
sl@0
   308
            case 1:
sl@0
   309
                
sl@0
   310
                if    (*where <= numeric_limits<TYPE_FLOAT>::epsilon())
sl@0
   311
                {
sl@0
   312
                    u =
sl@0
   313
                    w = static_cast<TYPE_FLOAT>(0);
sl@0
   314
                    v = static_cast<TYPE_FLOAT>(1);
sl@0
   315
                }
sl@0
   316
                else
sl@0
   317
                {
sl@0
   318
                    lambda = -y/vecnormsqr;
sl@0
   319
                    
sl@0
   320
                    u = lambda*x;
sl@0
   321
                    v = static_cast<TYPE_FLOAT>(1) + lambda*y;
sl@0
   322
                    w = lambda*z;
sl@0
   323
                }
sl@0
   324
                
sl@0
   325
                break;
sl@0
   326
                
sl@0
   327
            case 2:
sl@0
   328
                
sl@0
   329
                if    (*where <= numeric_limits<TYPE_FLOAT>::epsilon())
sl@0
   330
                {
sl@0
   331
                    u =
sl@0
   332
                    v = static_cast<TYPE_FLOAT>(0);
sl@0
   333
                    w = static_cast<TYPE_FLOAT>(1);
sl@0
   334
                }
sl@0
   335
                else
sl@0
   336
                {
sl@0
   337
                    lambda = -z/vecnormsqr;
sl@0
   338
                    
sl@0
   339
                    u = lambda*x;
sl@0
   340
                    v = lambda*y;
sl@0
   341
                    w = static_cast<TYPE_FLOAT>(1) + lambda*z;
sl@0
   342
                }
sl@0
   343
                
sl@0
   344
                break;
sl@0
   345
                
sl@0
   346
            default:
sl@0
   347
                
sl@0
   348
                ::std::string        error_reporting("Impossible condition in find_invariant_vector");
sl@0
   349
                ::std::logic_error   processing_error(error_reporting);
sl@0
   350
                
sl@0
   351
                throw(processing_error);
sl@0
   352
                
sl@0
   353
                break;
sl@0
   354
        }
sl@0
   355
        
sl@0
   356
        TYPE_FLOAT    vecnorm = sqrt(u*u+v*v+w*w);
sl@0
   357
        
sl@0
   358
        if    (vecnorm <= numeric_limits<TYPE_FLOAT>::epsilon())
sl@0
   359
        {
sl@0
   360
            ::std::string            error_reporting("Underflow error in find_orthogonal_vector!");
sl@0
   361
            ::std::underflow_error   processing_error(error_reporting);
sl@0
   362
            
sl@0
   363
            throw(processing_error);
sl@0
   364
        }
sl@0
   365
        
sl@0
   366
        u /= vecnorm;
sl@0
   367
        v /= vecnorm;
sl@0
   368
        w /= vecnorm;
sl@0
   369
    }
sl@0
   370
    
sl@0
   371
    
sl@0
   372
    // Note:    we want [[v, v, w], [r, s, t], [x, y, z]] to be a direct orthogonal basis
sl@0
   373
    //            of R^3. It might not be orthonormal, however, and we do not check if the
sl@0
   374
    //            two input vectors are colinear or not.
sl@0
   375
    
sl@0
   376
    template<typename TYPE_FLOAT>
sl@0
   377
    void    find_vector_for_BOD(TYPE_FLOAT x,
sl@0
   378
                                TYPE_FLOAT y,
sl@0
   379
                                TYPE_FLOAT z,
sl@0
   380
                                TYPE_FLOAT u, 
sl@0
   381
                                TYPE_FLOAT v,
sl@0
   382
                                TYPE_FLOAT w,
sl@0
   383
                                TYPE_FLOAT & r,
sl@0
   384
                                TYPE_FLOAT & s,
sl@0
   385
                                TYPE_FLOAT & t)
sl@0
   386
    {
sl@0
   387
        r = +y*w-z*v;
sl@0
   388
        s = -x*w+z*u;
sl@0
   389
        t = +x*v-y*u;
sl@0
   390
    }
sl@0
   391
sl@0
   392
sl@0
   393
sl@0
   394
template<typename TYPE_FLOAT>
sl@0
   395
inline bool                                is_R3_rotation_matrix(R3_matrix<TYPE_FLOAT> const & mat)
sl@0
   396
{
sl@0
   397
    using    ::std::abs;
sl@0
   398
    
sl@0
   399
    using    ::std::numeric_limits;
sl@0
   400
    
sl@0
   401
    return    (
sl@0
   402
                !(
sl@0
   403
                    (abs(mat.a11*mat.a11+mat.a21*mat.a21+mat.a31*mat.a31 - static_cast<TYPE_FLOAT>(1)) > static_cast<TYPE_FLOAT>(10)*numeric_limits<TYPE_FLOAT>::epsilon())||
sl@0
   404
                    (abs(mat.a11*mat.a12+mat.a21*mat.a22+mat.a31*mat.a32 - static_cast<TYPE_FLOAT>(0)) > static_cast<TYPE_FLOAT>(10)*numeric_limits<TYPE_FLOAT>::epsilon())||
sl@0
   405
                    (abs(mat.a11*mat.a13+mat.a21*mat.a23+mat.a31*mat.a33 - static_cast<TYPE_FLOAT>(0)) > static_cast<TYPE_FLOAT>(10)*numeric_limits<TYPE_FLOAT>::epsilon())||
sl@0
   406
                    //(abs(mat.a11*mat.a12+mat.a21*mat.a22+mat.a31*mat.a32 - static_cast<TYPE_FLOAT>(0)) > static_cast<TYPE_FLOAT>(10)*numeric_limits<TYPE_FLOAT>::epsilon())||
sl@0
   407
                    (abs(mat.a12*mat.a12+mat.a22*mat.a22+mat.a32*mat.a32 - static_cast<TYPE_FLOAT>(1)) > static_cast<TYPE_FLOAT>(10)*numeric_limits<TYPE_FLOAT>::epsilon())||
sl@0
   408
                    (abs(mat.a12*mat.a13+mat.a22*mat.a23+mat.a32*mat.a33 - static_cast<TYPE_FLOAT>(0)) > static_cast<TYPE_FLOAT>(10)*numeric_limits<TYPE_FLOAT>::epsilon())||
sl@0
   409
                    //(abs(mat.a11*mat.a13+mat.a21*mat.a23+mat.a31*mat.a33 - static_cast<TYPE_FLOAT>(0)) > static_cast<TYPE_FLOAT>(10)*numeric_limits<TYPE_FLOAT>::epsilon())||
sl@0
   410
                    //(abs(mat.a12*mat.a13+mat.a22*mat.a23+mat.a32*mat.a33 - static_cast<TYPE_FLOAT>(0)) > static_cast<TYPE_FLOAT>(10)*numeric_limits<TYPE_FLOAT>::epsilon())||
sl@0
   411
                    (abs(mat.a13*mat.a13+mat.a23*mat.a23+mat.a33*mat.a33 - static_cast<TYPE_FLOAT>(1)) > static_cast<TYPE_FLOAT>(10)*numeric_limits<TYPE_FLOAT>::epsilon())
sl@0
   412
                )
sl@0
   413
            );
sl@0
   414
}
sl@0
   415
sl@0
   416
sl@0
   417
template<typename TYPE_FLOAT>
sl@0
   418
::boost::math::quaternion<TYPE_FLOAT>    R3_rotation_to_quaternion(    R3_matrix<TYPE_FLOAT> const & rot,
sl@0
   419
                                                                    ::boost::math::quaternion<TYPE_FLOAT> const * hint = 0)
sl@0
   420
{
sl@0
   421
    using    ::boost::math::abs;
sl@0
   422
    
sl@0
   423
    using    ::std::abs;
sl@0
   424
    using    ::std::sqrt;
sl@0
   425
    
sl@0
   426
    using    ::std::numeric_limits;
sl@0
   427
    
sl@0
   428
    if    (!is_R3_rotation_matrix(rot))
sl@0
   429
    {
sl@0
   430
        ::std::string        error_reporting("Argument to R3_rotation_to_quaternion is not an R^3 rotation matrix!");
sl@0
   431
        ::std::range_error   bad_argument(error_reporting);
sl@0
   432
        
sl@0
   433
        throw(bad_argument);
sl@0
   434
    }
sl@0
   435
    
sl@0
   436
    ::boost::math::quaternion<TYPE_FLOAT>    q;
sl@0
   437
    
sl@0
   438
    if    (
sl@0
   439
            (abs(rot.a11 - static_cast<TYPE_FLOAT>(1)) <= numeric_limits<TYPE_FLOAT>::epsilon())&&
sl@0
   440
            (abs(rot.a22 - static_cast<TYPE_FLOAT>(1)) <= numeric_limits<TYPE_FLOAT>::epsilon())&&
sl@0
   441
            (abs(rot.a33 - static_cast<TYPE_FLOAT>(1)) <= numeric_limits<TYPE_FLOAT>::epsilon())
sl@0
   442
        )
sl@0
   443
    {
sl@0
   444
        q = ::boost::math::quaternion<TYPE_FLOAT>(1);
sl@0
   445
    }
sl@0
   446
    else
sl@0
   447
    {
sl@0
   448
        TYPE_FLOAT    cos_theta = (rot.a11+rot.a22+rot.a33-static_cast<TYPE_FLOAT>(1))/static_cast<TYPE_FLOAT>(2);
sl@0
   449
        TYPE_FLOAT    stuff = (cos_theta+static_cast<TYPE_FLOAT>(1))/static_cast<TYPE_FLOAT>(2);
sl@0
   450
        TYPE_FLOAT    cos_theta_sur_2 = sqrt(stuff);
sl@0
   451
        TYPE_FLOAT    sin_theta_sur_2 = sqrt(1-stuff);
sl@0
   452
        
sl@0
   453
        TYPE_FLOAT    x;
sl@0
   454
        TYPE_FLOAT    y;
sl@0
   455
        TYPE_FLOAT    z;
sl@0
   456
        
sl@0
   457
        find_invariant_vector(rot, x, y, z);
sl@0
   458
        
sl@0
   459
        TYPE_FLOAT    u;
sl@0
   460
        TYPE_FLOAT    v;
sl@0
   461
        TYPE_FLOAT    w;
sl@0
   462
        
sl@0
   463
        find_orthogonal_vector(x, y, z, u, v, w);
sl@0
   464
        
sl@0
   465
        TYPE_FLOAT    r;
sl@0
   466
        TYPE_FLOAT    s;
sl@0
   467
        TYPE_FLOAT    t;
sl@0
   468
        
sl@0
   469
        find_vector_for_BOD(x, y, z, u, v, w, r, s, t);
sl@0
   470
        
sl@0
   471
        TYPE_FLOAT    ru = rot.a11*u+rot.a12*v+rot.a13*w;
sl@0
   472
        TYPE_FLOAT    rv = rot.a21*u+rot.a22*v+rot.a23*w;
sl@0
   473
        TYPE_FLOAT    rw = rot.a31*u+rot.a32*v+rot.a33*w;
sl@0
   474
        
sl@0
   475
        TYPE_FLOAT    angle_sign_determinator = r*ru+s*rv+t*rw;
sl@0
   476
        
sl@0
   477
        if        (angle_sign_determinator > +numeric_limits<TYPE_FLOAT>::epsilon())
sl@0
   478
        {
sl@0
   479
            q = ::boost::math::quaternion<TYPE_FLOAT>(cos_theta_sur_2, +x*sin_theta_sur_2, +y*sin_theta_sur_2, +z*sin_theta_sur_2);
sl@0
   480
        }
sl@0
   481
        else if    (angle_sign_determinator < -numeric_limits<TYPE_FLOAT>::epsilon())
sl@0
   482
        {
sl@0
   483
            q = ::boost::math::quaternion<TYPE_FLOAT>(cos_theta_sur_2, -x*sin_theta_sur_2, -y*sin_theta_sur_2, -z*sin_theta_sur_2);
sl@0
   484
        }
sl@0
   485
        else
sl@0
   486
        {
sl@0
   487
            TYPE_FLOAT    desambiguator = u*ru+v*rv+w*rw;
sl@0
   488
            
sl@0
   489
            if    (desambiguator >= static_cast<TYPE_FLOAT>(1))
sl@0
   490
            {
sl@0
   491
                q = ::boost::math::quaternion<TYPE_FLOAT>(0, +x, +y, +z);
sl@0
   492
            }
sl@0
   493
            else
sl@0
   494
            {
sl@0
   495
                q = ::boost::math::quaternion<TYPE_FLOAT>(0, -x, -y, -z);
sl@0
   496
            }
sl@0
   497
        }
sl@0
   498
    }
sl@0
   499
    
sl@0
   500
    if    ((hint != 0) && (abs(*hint+q) < abs(*hint-q)))
sl@0
   501
    {
sl@0
   502
        return(-q);
sl@0
   503
    }
sl@0
   504
    
sl@0
   505
    return(q);
sl@0
   506
}
sl@0
   507
sl@0
   508
#endif /* TEST_HSO3_HPP */
sl@0
   509