POV-Ray : Newsgroups : povray.programming : POV-Ray on non-IEEE floating-point compatible platforms Server Time
23 Dec 2024 15:16:15 EST (-0500)
  POV-Ray on non-IEEE floating-point compatible platforms (Message 1 to 4 of 4)  
From: Thorsten Froehlich
Subject: POV-Ray on non-IEEE floating-point compatible platforms
Date: 21 Sep 2002 08:57:10
Message: <3d8c6ca6$1@news.povray.org>
While there are not many such platforms left, those who still need them and
have ISO C99 compatible libraries may want to try to adjust the ot_index_box
function in octree.cpp to use the logbf / ilogbf C99 library function, which
is available in most recent compilers for Unix platforms.  below is the
example code that demonstrates how to adapt the code.  The actual POV-Ray
code change is left as an exercise to the reader ;-)

    Thorsten


NOTE: Be aware that is is most likely far less efficient, but it is
compatible with ISO C99 libraries!  I only provide the version using logbf
because the library I used for testing listed ilogbf as not yet supported...


#include <stdio.h>
#include <math.h>

int main(void)
{
 union
 {
  float f;
  long l;
 }
 convert;

 convert.f = -8614.585434574;
 convert.l &= 0xff800000;

 printf("%f %f\n", pow(2.0, logbf(convert.f) *(1-2*signbit(convert.f)),
                   convert.f);

 convert.f = -84.585434574;
 convert.l &= 0x7f800000;

 printf("%f %x %d %d %d\n", convert.f, convert.l, (convert.l>>23)-127,
                            (convert.l>>23), ((int)logbf(convert.f))+127);

 return 0;
}


____________________________________________________
Thorsten Froehlich, Duisburg, Germany
e-mail: tho### [at] trfde

Visit POV-Ray on the web: http://mac.povray.org


Post a reply to this message

From: Christoph Hormann
Subject: Re: POV-Ray on non-IEEE floating-point compatible platforms
Date: 23 Sep 2002 05:51:33
Message: <3D8EE425.117C3945@gmx.de>
Thorsten Froehlich wrote:
> 
> While there are not many such platforms left, those who still need them and
> have ISO C99 compatible libraries may want to try to adjust the ot_index_box
> function in octree.cpp to use the logbf / ilogbf C99 library function, which
> is available in most recent compilers for Unix platforms.  below is the
> example code that demonstrates how to adapt the code.  The actual POV-Ray
> code change is left as an exercise to the reader ;-)

I don't know much about these different floating point formats, but
remember this part was exactly what caused problems when i last tried
using POV-Ray on a SGI machine.  Will your suggestion help there or is
that a different (64 bit specific) problem?

Christoph

-- 
POV-Ray tutorials, IsoWood include,                 
TransSkin and more: http://www.tu-bs.de/~y0013390/  
Last updated 13 Aug. 2002 _____./\/^>_*_<^\/\.______


Post a reply to this message

From: Thorsten Froehlich
Subject: Re: POV-Ray on non-IEEE floating-point compatible platforms
Date: 23 Sep 2002 08:05:38
Message: <3d8f0392$1@news.povray.org>
In article <3D8EE425.117C3945@gmx.de> , Christoph Hormann 
<chr### [at] gmxde>  wrote:

> I don't know much about these different floating point formats, but
> remember this part was exactly what caused problems when i last tried
> using POV-Ray on a SGI machine.  Will your suggestion help there or is
> that a different (64 bit specific) problem?

No, it also resolves the 64 bit specific problems.  Actually, the code below
may even work on 64 bit systems as is, because the actual bug was that the
conversion structure used 'long' rather than 'int', so it would attempt to
modify 64 bit data while it should have modified 32 bit data.

Replace the existing code with the functions shown below.  They should work
just fine now.  however, as a lack a 64 bit system to test on, I cannot tell
you for sure :-(

    Thorsten


/**************************************************************************
* Local preprocessor defines
***************************************************************************/

// WARNING: The default uses POV-Ray's own tricks which only work if
// "float" is a 32 bit IEEE 754 floating point number!  If your platform
// does not use 32 bit IEEE 754 floating point numbers, radiosity will
// be broken!!!  If you have this problem, your only other choice is to
// use an ISO C99 standard revision compatible compiler and library:
//
// Define this to 1 to use ISO C99 functions logbf, logb and copysign.
// Define this to 2 to use ISO C99 functions ilogbf, ilogb and copysign.
//
// You may want to try 1 and 2 as it cannot be generally said which one
// will be faster, but it is most likely that either 1 or 2 will perform
// slightly less well than POV-Ray's trick.  In any case, testing all
// variants (0, 1 and 2) is recommended if possible on your platform!
//
// NOTE: Of course you should put the define forC99_COMPATIBLE_RADIOSITY
// into config.h and *not* mess around with this file!!!
#ifndef C99_COMPATIBLE_RADIOSITY
#define C99_COMPATIBLE_RADIOSITY 0
#endif

int ot_point_in_node(VECTOR point, OT_ID *id)
{
  DBL sized, minx, miny, minz, lox, loy, loz, hix, hiy, hiz;

#if(C99_COMPATIBLE_RADIOSITY == 0)
  union
  {
    float f;
    int l;
  }
  size;                         /* MUST be float, NOT DBL */

  size.l = id->Size << 23;
  sized = (DBL) size.f;
#elif(C99_COMPATIBLE_RADIOSITY == 1)
  sized = pow(2.0, id->Size);
#else
  sized = (DBL)(1 << id->Size);
#endif
  minx = (DBL) id->x * sized - OT_BIAS;
  miny = (DBL) id->y * sized - OT_BIAS;
  minz = (DBL) id->z * sized - OT_BIAS;

  lox = minx - sized * .5;
  hix = minx + sized * 1.5;
  loy = miny - sized * .5;
  hiy = miny + sized * 1.5;
  loz = minz - sized * .5;
  hiz = minz + sized * 1.5;

  return(point[X] >= lox && point[X] < hix &&
         point[Y] >= loy && point[Y] < hiy &&
         point[Z] >= loz && point[Z] < hiz);
}


void ot_index_box(VECTOR min_point, VECTOR max_point, OT_ID *id)
{
  int done, idx, idy, idz;
  float dx, dy, dz, maxdel;     /* MUST BE "float" NOT "DBL" */
  DBL bsized, maxord;
#if(C99_COMPATIBLE_RADIOSITY == 0)
  union
  {
    float f;
    int l;
  }
  convert;
#endif
  OT_ID base_id, test_id;

  dx = (float) (max_point[X] - min_point[X]);
  dy = (float) (max_point[Y] - min_point[Y]);
  dz = (float) (max_point[Z] - min_point[Z]);
  maxdel = MAX3(dx, dy, dz);

  /*
   * This hex operation does a floor to next lower power of 2, by clearing
   * all of the mantissa bits.  Works only on IEEE single precision floats
   */
#if(C99_COMPATIBLE_RADIOSITY == 0)
  convert.f = maxdel;
  convert.l &= 0xff800000;
  bsized = (DBL)convert.f;
#elif(C99_COMPATIBLE_RADIOSITY == 1)
  bsized = pow(2.0, logbf(maxdel));
  bsized = copysign(bsized, maxdel);
#else
  bsized = (DBL)(1 << ilogbf(maxdel));
  bsized = copysign(bsized, maxdel);
#endif

#ifdef SAFE_METHOD

  /*
   * This block checks for the case where the node id would cause integer
   * overflow, since it is a small buffer far away
   */
  maxord = MAX3(fabs(min_point[X]), fabs(min_point[Y]), fabs(min_point[Z]));
  maxord += OT_BIAS;
  while (maxord / bsized > 1000000000.0)
  {
#ifdef RADSTATS
    overflows++;
#endif
    bsized *= 2.0;
  }
#endif

  /* calculate the smallest possible node that the item might fit into */
  base_id.x = (int) floor((min_point[X] + OT_BIAS) / bsized);
  base_id.y = (int) floor((min_point[Y] + OT_BIAS) / bsized);
  base_id.z = (int) floor((min_point[Z] + OT_BIAS) / bsized);

  /*
   * This magic hex operation extracts the exponent, which gives us an
   * integer number suitable for labelling a range of a power of 2.  In IEEE
   * format, value = pow(2,exponent-127). Therefore, if our index is, say,
   * 129, then the item has a maximum extent of (2 to the (129-127)), or
   * about 4 space units.
   */
#if(C99_COMPATIBLE_RADIOSITY == 0)
  convert.f = (float) bsized;
  base_id.Size = (convert.l & 0x7f800000) >> 23;
#elif(C99_COMPATIBLE_RADIOSITY == 1)
  base_id.Size = ((int)logb(bsized)) + 127;
#else
  base_id.Size = ilogb(bsized) + 127;
#endif

  /* Now increase the node size until it fits for sure */
#ifdef RADSTATS
  thisloops = 0;
#endif
  done = 0;
  while (!done)
  {
    test_id.Size = base_id.Size;
    for (idx = 0; idx < 2 && !done; idx++)
    {
      for (idy = 0; idy < 2 && !done; idy++)
      {
        for (idz = 0; idz < 2 && !done; idz++)
        {
          test_id.x = base_id.x + idx;
          test_id.y = base_id.y + idy;
          test_id.z = base_id.z + idz;
          if (ot_point_in_node(min_point, &test_id) &&
              ot_point_in_node(max_point, &test_id))
          {
            done = 1;
          }
        }
      }
    }

    /*
     * Debug_Info("looping %d,%d,%d,%d  min=%d, max=%d\n", test_id.x,
     * test_id.y,test_id.z, test_id.Size, ot_point_in_node(min_point,
     * &test_id), ot_point_in_node(max_point, &test_id));
     */
    ot_parent(&base_id, &base_id);
#ifdef RADSTATS
    totloops++;
    thisloops++;
#endif
  }
#ifdef RADSTATS
  if (thisloops < minloops)
    minloops = thisloops;
  if (thisloops > maxloops)
    maxloops = thisloops;
#endif
  *id = test_id;

#ifdef OT_DEBUG
  if (id->Size > 139)
  {
    Debug_Info("unusually large id, maxdel=%.4f, bsized=%.4f, isize=%d\n",
           maxdel, bsized, id->Size);
  }
#endif
}




____________________________________________________
Thorsten Froehlich, Duisburg, Germany
e-mail: tho### [at] trfde

Visit POV-Ray on the web: http://mac.povray.org


Post a reply to this message

From: Thomas van der Veen
Subject: Re: POV-Ray on non-IEEE floating-point compatible platforms
Date: 23 Sep 2002 12:45:51
Message: <Xns9292B4B50D16Eveentukibmcom@204.213.191.226>
"Thorsten Froehlich" <tho### [at] trfde> wrote in
news:3d8f0392$1@news.povray.org: 

> Replace the existing code with the functions shown below.  They should
> work just fine now.  however, as a lack a 64 bit system to test on, I
> cannot tell you for sure :-(

UNfortunatly I have ver y littel time to give this a try ... :( 

Maybe someone else can give it a try.


Thomas


Post a reply to this message

Copyright 2003-2023 Persistence of Vision Raytracer Pty. Ltd.