/* SCE CONFIDENTIAL
PLAYSTATION(R)3 Programmer Tool Runtime Library 084.006
* Copyright (C) 2004 Sony Computer Entertainment Inc. 
* All Rights Reserved.
*/
#define _LOGF_H_ln2msb    ((float)(0.6931470632553f))
#define _LOGF_H_negln2lsb ((float)(-1.1730463525e-7f))

#define _LOGF_H_c0 ((float)(-0.2988439998f)) 
#define _LOGF_H_c1 ((float)(-0.3997655209f))
#define _LOGF_H_c2 ((float)(-0.6666679125f))

_FUNC_DEF(vec_float4, logf4, (vec_float4 x)) 
{
  vec_int4 zeros = (vec_int4)(0);
  vec_float4 ones = (vec_float4)(1.0f);
  //vec_uchar16 zeromask = (vec_uchar16)vec_cmpeq(x, (vec_float4)zeros);

  vec_int4 expmask = (vec_int4)(0x7F800000);
  vec_int4 xexp = vec_add( vec_sr(vec_and((vec_int4)x, expmask), (vec_uint4)(23)), (vec_int4)(-126) );
  x = vec_sel(x, (vec_float4)((vec_int4)(0x3F000000)), (vec_uint4)expmask);


  vec_uint4  mask = (vec_uint4)vec_cmpgt((vec_float4)((float)0.7071067811865f), x);
  x    = vec_sel(x   , vec_add(x, x)                   , mask);
  xexp = vec_sel(xexp, vec_sub(xexp,(vec_int4)(1)), mask);
  
  vec_float4 x1 = vec_sub(x , ones);
  vec_float4 z  = divf4  (x1, vec_add(x, ones));
  vec_float4 w  = vec_madd(z , z, (vec_float4)zeros);
  vec_float4 polywneg;
  polywneg = vec_madd((vec_float4)(_LOGF_H_c0), w, (vec_float4)(_LOGF_H_c1));
  polywneg = vec_madd(polywneg                , w, (vec_float4)(_LOGF_H_c2));

  vec_float4 y    = vec_madd(z, vec_madd(polywneg, w, x1), (vec_float4)zeros);
  vec_float4 wnew = vec_ctf(xexp,0);
  vec_float4 zz1     = vec_madd((vec_float4)(_LOGF_H_ln2msb)   , wnew, x1);
  vec_float4 zz2neg  = vec_madd((vec_float4)(_LOGF_H_negln2lsb), wnew, y );

  //return vec_sel(vec_sub(zz1,zz2neg), (vec_float4)zeromask, zeromask);
  return vec_sub(zz1,zz2neg);
}
