Movatterモバイル変換


[0]ホーム

URL:


{-# LANGUAGE Trustworthy #-}{-# LANGUAGE CPP, MagicHash, UnboxedTuples, NoImplicitPrelude #-}{-# OPTIONS_HADDOCK hide #-}------------------------------------------------------------------------------- |-- Module      :  GHC.Float.RealFracMethods-- Copyright   :  (c) Daniel Fischer 2010-- License     :  see libraries/base/LICENSE---- Maintainer  :  cvs-ghc@haskell.org-- Stability   :  internal-- Portability :  non-portable (GHC Extensions)---- Methods for the RealFrac instances for 'Float' and 'Double',-- with specialised versions for 'Int'.---- Moved to their own module to not bloat GHC.Float further.-------------------------------------------------------------------------------#include "MachDeps.h"moduleGHC.Float.RealFracMethods(-- * Double methods-- ** Integer resultsproperFractionDoubleInteger,truncateDoubleInteger,floorDoubleInteger,ceilingDoubleInteger,roundDoubleInteger-- ** Int results,properFractionDoubleInt,floorDoubleInt,ceilingDoubleInt,roundDoubleInt-- * Double/Int conversions, wrapped primops,double2Int,int2Double-- * Float methods-- ** Integer results,properFractionFloatInteger,truncateFloatInteger,floorFloatInteger,ceilingFloatInteger,roundFloatInteger-- ** Int results,properFractionFloatInt,floorFloatInt,ceilingFloatInt,roundFloatInt-- * Float/Int conversions, wrapped primops,float2Int,int2Float)whereimportGHC.IntegerimportGHC.BaseimportGHC.Num()#if WORD_SIZE_IN_BITS < 64importGHC.IntWord64#define TO64 integerToInt64#define FROM64 int64ToInteger#define MINUS64 minusInt64##define NEGATE64 negateInt64##else#define TO64 integerToInt#define FROM64 smallInteger#define MINUS64 ( -# )#define NEGATE64 negateInt#uncheckedIShiftRA64#::Int#->Int#->Int#uncheckedIShiftRA64#=uncheckedIShiftRA#uncheckedIShiftL64#::Int#->Int#->Int#uncheckedIShiftL64#=uncheckedIShiftL##endifdefault()--------------------------------------------------------------------------------                              Float Methods                               ---------------------------------------------------------------------------------- Special Functions for Int, nice, easy and fast.-- They should be small enough to be inlined automatically.-- We have to test for ±0.0 to avoid returning -0.0 in the second-- component of the pair. Unfortunately the branching costs a lot-- of performance.properFractionFloatInt::Float->(Int,Float)properFractionFloatInt(F#x)=ifisTrue#(x`eqFloat#`0.0#)then(I#0#,F#0.0#)elsecasefloat2Int#xofn->(I#n,F#(x`minusFloat#`int2Float#n))-- truncateFloatInt = float2IntfloorFloatInt::Float->IntfloorFloatInt(F#x)=casefloat2Int#xofn|isTrue#(x`ltFloat#`int2Float#n)->I#(n-#1#)|otherwise->I#nceilingFloatInt::Float->IntceilingFloatInt(F#x)=casefloat2Int#xofn|isTrue#(int2Float#n`ltFloat#`x)->I#(n+#1#)|otherwise->I#nroundFloatInt::Float->IntroundFloatIntx=float2Int(c_rintFloatx)-- Functions with Integer results-- With the new code generator in GHC 7, the explicit bit-fiddling is-- slower than the old code for values of small modulus, but when the-- 'Int' range is left, the bit-fiddling quickly wins big, so we use that.-- If the methods are called on smallish values, hopefully people go-- through Int and not larger types.-- Note: For negative exponents, we must check the validity of the shift-- distance for the right shifts of the mantissa.{-# INLINEproperFractionFloatInteger#-}properFractionFloatInteger::Float->(Integer,Float)properFractionFloatIntegerv@(F#x)=casedecodeFloat_Int#xof(#m,e#)|isTrue#(e<#0#)->casenegateInt#eofs|isTrue#(s>#23#)->(0,v)|isTrue#(m<#0#)->casenegateInt#(negateInt#m`uncheckedIShiftRA#`s)ofk->(smallIntegerk,casem-#(k`uncheckedIShiftL#`s)ofr->F#(encodeFloatInteger(smallIntegerr)e))|otherwise->casem`uncheckedIShiftRL#`sofk->(smallIntegerk,casem-#(k`uncheckedIShiftL#`s)ofr->F#(encodeFloatInteger(smallIntegerr)e))|otherwise->(shiftLInteger(smallIntegerm)e,F#0.0#){-# INLINEtruncateFloatInteger#-}truncateFloatInteger::Float->IntegertruncateFloatIntegerx=caseproperFractionFloatIntegerxof(n,_)->n-- floor is easier for negative numbers than truncate, so this gets its-- own implementation, it's a little faster.{-# INLINEfloorFloatInteger#-}floorFloatInteger::Float->IntegerfloorFloatInteger(F#x)=casedecodeFloat_Int#xof(#m,e#)|isTrue#(e<#0#)->casenegateInt#eofs|isTrue#(s>#23#)->ifisTrue#(m<#0#)then(-1)else0|otherwise->smallInteger(m`uncheckedIShiftRA#`s)|otherwise->shiftLInteger(smallIntegerm)e-- ceiling x = -floor (-x)-- If giving this its own implementation is faster at all,-- it's only marginally so, hence we keep it short.{-# INLINEceilingFloatInteger#-}ceilingFloatInteger::Float->IntegerceilingFloatInteger(F#x)=negateInteger(floorFloatInteger(F#(negateFloat#x))){-# INLINEroundFloatInteger#-}roundFloatInteger::Float->IntegerroundFloatIntegerx=float2Integer(c_rintFloatx)--------------------------------------------------------------------------------                              Double Methods                              ---------------------------------------------------------------------------------- Special Functions for Int, nice, easy and fast.-- They should be small enough to be inlined automatically.-- We have to test for ±0.0 to avoid returning -0.0 in the second-- component of the pair. Unfortunately the branching costs a lot-- of performance.properFractionDoubleInt::Double->(Int,Double)properFractionDoubleInt(D#x)=ifisTrue#(x==##0.0##)then(I#0#,D#0.0##)elsecasedouble2Int#xofn->(I#n,D#(x-##int2Double#n))-- truncateDoubleInt = double2IntfloorDoubleInt::Double->IntfloorDoubleInt(D#x)=casedouble2Int#xofn|isTrue#(x<##int2Double#n)->I#(n-#1#)|otherwise->I#nceilingDoubleInt::Double->IntceilingDoubleInt(D#x)=casedouble2Int#xofn|isTrue#(int2Double#n<##x)->I#(n+#1#)|otherwise->I#nroundDoubleInt::Double->IntroundDoubleIntx=double2Int(c_rintDoublex)-- Functions with Integer results-- The new Code generator isn't quite as good for the old 'Double' code-- as for the 'Float' code, so for 'Double' the bit-fiddling also wins-- when the values have small modulus.-- When the exponent is negative, all mantissae have less than 64 bits-- and the right shifting of sized types is much faster than that of-- 'Integer's, especially when we can-- Note: For negative exponents, we must check the validity of the shift-- distance for the right shifts of the mantissa.{-# INLINEproperFractionDoubleInteger#-}properFractionDoubleInteger::Double->(Integer,Double)properFractionDoubleIntegerv@(D#x)=casedecodeDoubleIntegerxof(#m,e#)|isTrue#(e<#0#)->casenegateInt#eofs|isTrue#(s>#52#)->(0,v)|m<0->caseTO64(negateIntegerm)ofn->casen`uncheckedIShiftRA64#`sofk->(FROM64(NEGATE64k),caseMINUS64n(k`uncheckedIShiftL64#`s)ofr->D#(encodeDoubleInteger(FROM64(NEGATE64r))e))|otherwise->caseTO64mofn->casen`uncheckedIShiftRA64#`sofk->(FROM64k,caseMINUS64n(k`uncheckedIShiftL64#`s)ofr->D#(encodeDoubleInteger(FROM64r)e))|otherwise->(shiftLIntegerme,D#0.0##){-# INLINEtruncateDoubleInteger#-}truncateDoubleInteger::Double->IntegertruncateDoubleIntegerx=caseproperFractionDoubleIntegerxof(n,_)->n-- floor is easier for negative numbers than truncate, so this gets its-- own implementation, it's a little faster.{-# INLINEfloorDoubleInteger#-}floorDoubleInteger::Double->IntegerfloorDoubleInteger(D#x)=casedecodeDoubleIntegerxof(#m,e#)|isTrue#(e<#0#)->casenegateInt#eofs|isTrue#(s>#52#)->ifm<0then(-1)else0|otherwise->caseTO64mofn->FROM64(n`uncheckedIShiftRA64#`s)|otherwise->shiftLIntegerme{-# INLINEceilingDoubleInteger#-}ceilingDoubleInteger::Double->IntegerceilingDoubleInteger(D#x)=negateInteger(floorDoubleInteger(D#(negateDouble#x))){-# INLINEroundDoubleInteger#-}roundDoubleInteger::Double->IntegerroundDoubleIntegerx=double2Integer(c_rintDoublex)-- Wrappers around double2Int#, int2Double#, float2Int# and int2Float#,-- we need them here, so we move them from GHC.Float and re-export them-- explicitly from there.double2Int::Double->Intdouble2Int(D#x)=I#(double2Int#x)int2Double::Int->Doubleint2Double(I#i)=D#(int2Double#i)float2Int::Float->Intfloat2Int(F#x)=I#(float2Int#x)int2Float::Int->Floatint2Float(I#i)=F#(int2Float#i)-- Quicker conversions from 'Double' and 'Float' to 'Integer',-- assuming the floating point value is integral.---- Note: Since the value is integral, the exponent can't be less than-- (-TYP_MANT_DIG), so we need not check the validity of the shift-- distance for the right shfts here.{-# INLINEdouble2Integer#-}double2Integer::Double->Integerdouble2Integer(D#x)=casedecodeDoubleIntegerxof(#m,e#)|isTrue#(e<#0#)->caseTO64mofn->FROM64(n`uncheckedIShiftRA64#`negateInt#e)|otherwise->shiftLIntegerme{-# INLINEfloat2Integer#-}float2Integer::Float->Integerfloat2Integer(F#x)=casedecodeFloat_Int#xof(#m,e#)|isTrue#(e<#0#)->smallInteger(m`uncheckedIShiftRA#`negateInt#e)|otherwise->shiftLInteger(smallIntegerm)e-- Foreign imports, the rounding is done faster in C when the value-- isn't integral, so we call out for rounding. For values of large-- modulus, calling out to C is slower than staying in Haskell, but-- presumably 'round' is mostly called for values with smaller modulus,-- when calling out to C is a major win.-- For all other functions, calling out to C gives at most a marginal-- speedup for values of small modulus and is much slower than staying-- in Haskell for values of large modulus, so those are done in Haskell.foreignimportccallunsafe"rintDouble"c_rintDouble::Double->Doubleforeignimportccallunsafe"rintFloat"c_rintFloat::Float->Float

[8]ページ先頭

©2009-2025 Movatter.jp