{-# LANGUAGE BangPatterns #-}
import Escena
import Elem3D
    ( Foton,
      Luz(..),
      RGB(..),
      Base(Base),
      Ray,
      Direction(Direction),
      Point3D(..),
      escalatePoint,escalatePointt,
      degToRad,
      rotatePoint,movePoint, divRGB,rotatePointt
    )
import Figuras
    ( Obj,
      Shape(Sphere, Plane, Cylinder,Rectangle,Acelerator),
      Plano(Plano),
      Esfera(Esfera),
      Cilindro(Cilindro),
      Rectangulo(Rectangulo),
      Camara(Camara),
      BVH(BVH),
      Point2D(..),
      addFigMult,
      parametricShapeCollision,
      loadObjFile,
      convertToCustomFormat, encenderShape ,encenderShapes, buildBVH
      )
import Files (writePPM, rgbToString, readObject)
import Tone_map (gammaFunc,clamp)
import Funciones
    ( mediaLRGB,
      generateRaysForPixels,
      obtenerPrimeraColision,
      listRay,
      chunksOf, mulCam ,brdf, sumFlLuz)
import PathTracer (pathTracer, luzDirecta, luzArea)
import KdT ( createKD )
import PhotonMap ( photonMap )
import Data.KdTree.Static ( KdTree )
import Files (writeObject)
import Debug.Trace (trace,traceEventIO)
import System.Random (StdGen, newStdGen, split)
import Data.List (transpose)
import System.CPUTime (getCPUTime)
import System.Environment (getArgs)
import System.Exit (exitFailure)
import Text.Read (readMaybe)
import PhotonMap (createPhoton)
import qualified Data.DList as DL
import qualified Data.Set as Set

-- make clean && make simulacion && cd ./tmp && ./simulacion && ./run.sh && cd .. && convert ./tmp/output.ppm a.bmp

-- | Función principal que le aplica antialiasing a la imagen.
{-# INLINE antialiasing #-}
antialiasing :: Int -> [Obj] -> [Obj]
antialiasing :: Int -> [Obj] -> [Obj]
antialiasing Int
n [Obj]
rayos = (Set Obj -> Obj) -> [Set Obj] -> [Obj]
forall a b. (a -> b) -> [a] -> [b]
map Set Obj -> Obj
obtenerPrimeraColision ([Set Obj] -> [Obj]) -> [Set Obj] -> [Obj]
forall a b. (a -> b) -> a -> b
$ ([Obj] -> Set Obj) -> [[Obj]] -> [Set Obj]
forall a b. (a -> b) -> [a] -> [b]
map [Obj] -> Set Obj
forall a. Ord a => [a] -> Set a
Set.fromList (Int -> [Obj] -> [[Obj]]
forall e. Int -> [e] -> [[e]]
chunksOf Int
n [Obj]
rayos) -- Obtiene la colision mas cercana de cada lista de colisiones dependiendo del numero de rayos del antialiasing

-- | Función principal que hace el render con path tracing.
{-# INLINE listRayToRGB #-}
listRayToRGB :: [Luz] -> Set.Set Shape -> [Ray] -> StdGen -> Int -> [RGB]
listRayToRGB :: [Luz] -> Set Shape -> [Ray] -> StdGen -> Int -> [RGB]
listRayToRGB [Luz]
luz Set Shape
figuras [Ray]
rayos StdGen
gen Int
nRay = [RGB]
colorDirecto--zipWith (+) colorDirecto $ map (`divRGB` fromIntegral ppp) colorIndirecto
  --map (`divRGB` fromIntegral ppp) colorArea 
  where
    antial :: [Obj]
antial = (Set Obj -> Obj) -> [Set Obj] -> [Obj]
forall a b. (a -> b) -> [a] -> [b]
map Set Obj -> Obj
listRay ([Set Obj] -> [Obj]) -> [Set Obj] -> [Obj]
forall a b. (a -> b) -> a -> b
$ Set Shape -> [Ray] -> [Set Obj]
parametricShapeCollision Set Shape
figuras [Ray]
rayos
    rayColisions :: [Obj]
rayColisions = Int -> [Obj] -> [Obj]
antialiasing Int
nRay [Obj]
antial
    
    ([StdGen]
gens, [StdGen]
_) = Int -> [StdGen] -> ([StdGen], [StdGen])
forall a. Int -> [a] -> ([a], [a])
splitAt ([Obj] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Obj]
rayColisions Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
ppp) ([StdGen] -> ([StdGen], [StdGen]))
-> [StdGen] -> ([StdGen], [StdGen])
forall a b. (a -> b) -> a -> b
$ Int -> [StdGen] -> [StdGen]
forall a. Int -> [a] -> [a]
drop Int
1 ([StdGen] -> [StdGen]) -> [StdGen] -> [StdGen]
forall a b. (a -> b) -> a -> b
$ (StdGen -> StdGen) -> StdGen -> [StdGen]
forall a. (a -> a) -> a -> [a]
iterate ((StdGen, StdGen) -> StdGen
forall a b. (a, b) -> b
snd ((StdGen, StdGen) -> StdGen)
-> (StdGen -> (StdGen, StdGen)) -> StdGen -> StdGen
forall b c a. (b -> c) -> (a -> b) -> a -> c
. StdGen -> (StdGen, StdGen)
forall g. RandomGen g => g -> (g, g)
split) StdGen
gen  -- Semillas

    ppp :: Int
ppp = Int
256 -- Caminos por pixel
    colorIndirecto :: [RGB]
colorIndirecto =(Obj -> StdGen -> RGB) -> [Obj] -> [StdGen] -> [RGB]
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith (Float -> [Luz] -> Set Shape -> Int -> Obj -> StdGen -> RGB
pathTracer Float
1 [Luz]
luz Set Shape
figuras Int
ppp) [Obj]
rayColisions [StdGen]
gens
    colorDirecto :: [RGB]
colorDirecto = (Obj -> RGB) -> [Obj] -> [RGB]
forall a b. (a -> b) -> [a] -> [b]
map ([Luz] -> Set Shape -> Obj -> RGB
luzDirecta [Luz]
luz Set Shape
figuras) [Obj]
rayColisions
    colorArea :: [RGB]
colorArea = (Obj -> StdGen -> RGB) -> [Obj] -> [StdGen] -> [RGB]
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith (Set Shape -> Int -> Obj -> StdGen -> RGB
luzArea Set Shape
figuras Int
ppp) [Obj]
rayColisions [StdGen]
gens

-- | Función principal que hace el render con photon mapping.
{-# INLINE listRayPhoton #-}
listRayPhoton :: KdTree Float Foton -> [Luz] ->Point3D -> Set.Set Shape -> [Ray] -> Int -> [RGB]
listRayPhoton :: KdTree Float Foton
-> [Luz] -> Point3D -> Set Shape -> [Ray] -> Int -> [RGB]
listRayPhoton KdTree Float Foton
kdt [Luz]
luces Point3D
cam Set Shape
figuras [Ray]
rayos Int
nRay = (Obj -> RGB) -> [Obj] -> [RGB]
forall a b. (a -> b) -> [a] -> [b]
map (KdTree Float Foton -> [Luz] -> Float -> Set Shape -> Obj -> RGB
photonMap KdTree Float Foton
kdt [Luz]
luces Float
radio Set Shape
figuras) [Obj]
rayColisions
  where
    !raySMPP :: [Obj]
raySMPP = (Set Obj -> Obj) -> [Set Obj] -> [Obj]
forall a b. (a -> b) -> [a] -> [b]
map Set Obj -> Obj
listRay ([Set Obj] -> [Obj]) -> [Set Obj] -> [Obj]
forall a b. (a -> b) -> a -> b
$ Set Shape -> [Ray] -> [Set Obj]
parametricShapeCollision Set Shape
figuras [Ray]
rayos
    rayColisions :: [Obj]
rayColisions = Int -> [Obj] -> [Obj]
antialiasing Int
nRay [Obj]
raySMPP
    radio :: Float
radio = Float
4


main :: IO ()
IO ()
main = do

--   (vertices1, triangles7) <- loadObjFile "../meshes/simple/palace7.obj"  
--   (_, triangles6) <- loadObjFile "../meshes/simple/palace6.obj" 
--   (_, triangles5) <- loadObjFile "../meshes/simple/palace5.obj" 
--   (_, triangles4) <- loadObjFile "../meshes/simple/palace4.obj" 
--   (_, triangles3) <- loadObjFile "../meshes/simple/palace3.obj" 
--   (_, triangles2) <- loadObjFile "../meshes/simple/palace2.obj" 
--   (_, triangles1) <- loadObjFile "../meshes/simple/palace1.obj" 
--   (_, triangles0) <- loadObjFile "../meshes/simple/palace0.obj" 

--   let !vertices1' = map (escalatePointt (4).movePoint (Direction 7.5 (-2.5) (-9.75)). rotatePointt 'Y' (287.5) ) vertices1
--       !customTriangles7 = convertToCustomFormat (RGB 220 120 50) (0.85, 0,0) 0 (vertices1', triangles7)
--       !customTriangles6 = convertToCustomFormat (RGB 220 120 50) (0.85, 0,0) 0 (vertices1', triangles6)
--       !customTriangles5 = convertToCustomFormat (RGB 220 120 50) (0.85, 0,0) 0 (vertices1', triangles5)
--       !customTriangles4 = convertToCustomFormat (RGB 220 120 50) (0.85, 0,0) 0 (vertices1', triangles4)
--       !customTriangles3 = convertToCustomFormat (RGB 220 120 50) (0.85, 0,0) 0 (vertices1', triangles3)
--       !customTriangles2 = convertToCustomFormat (RGB 220 120 50) (0.85, 0,0) 0 (vertices1', triangles2)
--       !customTriangles1 = convertToCustomFormat (RGB 220 120 50) (0.85, 0,0) 0 (vertices1', triangles1)
--       !customTriangles0 = convertToCustomFormat (RGB 220 120 50) (0.85, 0,0) 0 (vertices1', triangles0)
--       !boundingVol7 = buildBVH 1000 customTriangles7
--       !boundingVol6 = buildBVH 2000 customTriangles6
--       !boundingVol5 = buildBVH 3000 customTriangles5
--       !boundingVol4 = buildBVH 4000 customTriangles4
--       !boundingVol3 = buildBVH 5000 customTriangles3
--       !boundingVol2 = buildBVH 6000 customTriangles2
--       !boundingVol1 = buildBVH 7000 customTriangles1
--       !boundingVol0 = buildBVH 8000 customTriangles0

--       figuras' =  Set.fromList $ addFigMult [(Acelerator boundingVol0),(Acelerator boundingVol1) ,(Acelerator boundingVol2),(Acelerator boundingVol3),(Acelerator boundingVol4),(Acelerator boundingVol5),(Acelerator boundingVol6),(Acelerator boundingVol7) ] $ Set.toList figuras

--   (verticesB1, trianglesB0) <- loadObjFile "../meshes/simple/botijo0.obj"  
  

--   let !verticesB1' = map (escalatePointt (4).movePoint (Direction 0 (-2) (0)). rotatePointt 'Y' (0) ) verticesB1
--       !customTrianglesB0 = convertToCustomFormat (RGB 220 120 50) (0.85, 0,0) 0 (verticesB1', trianglesB0)
--       !boundingVolB0 = buildBVH 1000 customTrianglesB0
--       !customTrianglesB1 = convertToCustomFormat (RGB 220 120 50) (0.85, 0,0) 0 ((map (movePoint (Direction (-8) (0) (0)) ) verticesB1'), trianglesB0)
--       !boundingVolB1 = buildBVH 1000 customTrianglesB1
--       !customTrianglesB2= convertToCustomFormat (RGB 20 120 220) (0.85, 0,0) 0 ((map (movePoint (Direction (-2) (0) (3)) ) verticesB1'), trianglesB0)
--       !boundingVolB2= buildBVH 1000 customTrianglesB2
--       !customTrianglesB3 = convertToCustomFormat (RGB 120 220 50) (0.85, 0,0) 0 ((map (movePoint (Direction 4 (0) ((-3))) )verticesB1'), trianglesB0)
--       !boundingVolB3 = buildBVH 1000 customTrianglesB3
--       !customTrianglesB4 = convertToCustomFormat (RGB 100 120 200) (0.85, 0,0) 0 ((map (movePoint (Direction 0 (5) (-8)) )verticesB1'), trianglesB0)
--       !boundingVolB4 = buildBVH 1000 customTrianglesB4
--       !customTrianglesB5 = convertToCustomFormat (RGB 0 220 0) (0.85, 0,0) 0 ((map (movePoint (Direction 0 (0) (-15)) )verticesB1'), trianglesB0)
--       !boundingVolB5 = buildBVH 1000 customTrianglesB5
--       figuras'' =  Set.fromList $ addFigMult [(Acelerator boundingVolB0),(Acelerator boundingVolB1),(Acelerator boundingVolB2),(Acelerator boundingVolB3),(Acelerator boundingVolB4),(Acelerator boundingVolB5)] $ Set.toList figuras'

  -- let objFilePath2 = "../meshes/simplehaskell.obj"  
  -- (vertices2, trianglesH2) <- loadObjFile objFilePath2
  -- let vertices2' = map (escalatePointt (2).movePoint (Direction (-5) (-5) (-8)). rotatePointt 'Y' (90)) vertices2
  --     customTrianglesH2 = convertToCustomFormat (RGB 122 10 255) (0.85, 0,0) 0 (vertices2', trianglesH2)
  --     boundingVol'' = buildBVH 4000 customTrianglesH2
  --     figuras''' =  Set.fromList $ addFigMult [Acelerator boundingVol''] (Set.toList figuras)    
  
  let objFilePath2 :: String
objFilePath2 = String
"../meshes/haskell.obj"  
  ([Point2D]
texturas2, [Point3D]
vertices2, [[TrianglePos]]
trianglesH2) <- String -> IO ([Point2D], [Point3D], [[TrianglePos]])
loadObjFile String
objFilePath2
  let vertices2' :: [Point3D]
vertices2' = (Point3D -> Point3D) -> [Point3D] -> [Point3D]
forall a b. (a -> b) -> [a] -> [b]
map (Float -> Point3D -> Point3D
escalatePointt (Float
1.5)(Point3D -> Point3D) -> (Point3D -> Point3D) -> Point3D -> Point3D
forall b c a. (b -> c) -> (a -> b) -> a -> c
.Direction -> Point3D -> Point3D
movePoint (Float -> Float -> Float -> Direction
Direction (-Float
3) (-Float
1) (-Float
7))(Point3D -> Point3D) -> (Point3D -> Point3D) -> Point3D -> Point3D
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Char -> Float -> Point3D -> Point3D
rotatePointt Char
'Y' (Float
90)) [Point3D]
vertices2
      origtrianglesH2 :: [TrianglePos]
origtrianglesH2 = ([TrianglePos] -> TrianglePos) -> [[TrianglePos]] -> [TrianglePos]
forall a b. (a -> b) -> [a] -> [b]
map ([TrianglePos] -> TrianglePos
forall a. [a] -> a
head) [[TrianglePos]]
trianglesH2
      textTrianglesH2 :: [TrianglePos]
textTrianglesH2 = ([TrianglePos] -> TrianglePos) -> [[TrianglePos]] -> [TrianglePos]
forall a b. (a -> b) -> [a] -> [b]
map ([TrianglePos] -> Int -> TrianglePos
forall a. [a] -> Int -> a
!! Int
1) [[TrianglePos]]
trianglesH2
      -- texturas2' = if length texturas2 == 0 then [Point2D 0 0] else texturas2
      customTrianglesH2 :: [Triangulo]
customTrianglesH2 = RGB
-> (Float, Float, Float)
-> Float
-> Int
-> ([Point3D], [TrianglePos], [Point2D], [TrianglePos])
-> [Triangulo]
convertToCustomFormat (Float -> Float -> Float -> RGB
RGB Float
122 Float
10 Float
255) (Float
0.85, Float
0,Float
0) Float
0 (Set Shape -> Int
forall a. Set a -> Int
Set.size Set Shape
figuras) ([Point3D]
vertices2', [TrianglePos]
origtrianglesH2, [Point2D]
texturas2, [TrianglePos]
textTrianglesH2)
      boundingVol'' :: BVH
boundingVol'' = Int -> [Triangulo] -> BVH
buildBVH Int
4000 [Triangulo]
customTrianglesH2
      figuras''' :: Set Shape
figuras''' =  [Shape] -> Set Shape
forall a. Ord a => [a] -> Set a
Set.fromList ([Shape] -> Set Shape) -> [Shape] -> Set Shape
forall a b. (a -> b) -> a -> b
$ [Shape] -> [Shape] -> [Shape]
addFigMult [BVH -> Shape
Acelerator BVH
boundingVol''] (Set Shape -> [Shape]
forall a. Set a -> [a]
Set.toList Set Shape
figuras)    
  
  -- let objFilePath2 = "../meshes/duck.obj"  
  -- (texturas2, vertices2, trianglesH2) <- loadObjFile objFilePath2
  -- let vertices2' = map (escalatePointt (2).movePoint (Direction (0) (0) (0)). rotatePointt 'Y' (0)) vertices2
  --     origtrianglesH2 = map (head) trianglesH2
  --     textTrianglesH2 = map (!! 1) trianglesH2
  --     -- texturas2' = if length texturas2 == 0 then [Point2D 0 0] else texturas2
  --     customTrianglesH2 = convertToCustomFormat (RGB 122 10 255) (0.85, 0,0) 0 (Set.size figuras) (vertices2', origtrianglesH2, texturas2, textTrianglesH2)
  --     boundingVol'' = buildBVH 4000 customTrianglesH2
  --     figuras''' =  Set.fromList $ addFigMult [Acelerator boundingVol''] (Set.toList figuras)    
    

  [String]
args <- IO [String]
getArgs
  case (String -> Maybe Int) -> [String] -> [Maybe Int]
forall a b. (a -> b) -> [a] -> [b]
map String -> Maybe Int
forall a. Read a => String -> Maybe a
readMaybe [String]
args of
    [Just Int
nStr, Just Int
mStr, Just Int
oStr] -> do
      StdGen
gen <- IO StdGen
forall (m :: * -> *). MonadIO m => m StdGen
newStdGen
      StdGen
gen' <- IO StdGen
forall (m :: * -> *). MonadIO m => m StdGen
newStdGen
      let n :: Int
n = Int
nStr :: Int
      let etapaY :: Int
etapaY = Int
mStr :: Int
      let etapaX :: Int
etapaX = Int
oStr :: Int
      let n' :: Int
n' = Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
+ (Int
etapaY Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
maxN)
      String -> IO ()
putStrLn (String -> IO ()) -> String -> IO ()
forall a b. (a -> b) -> a -> b
$ String
"The value of 'n' is: " String -> String -> String
forall a. [a] -> [a] -> [a]
++ Int -> String
forall a. Show a => a -> String
show Int
n'
      Integer
start <- IO Integer
getCPUTime
            
      [Foton]
notkdt <- String -> IO [Foton]
forall a. Binary a => String -> IO a
readObject String
"./kd.bin" -- Carga la lista de fotones del binario
      let kdt :: KdTree Float Foton
kdt = [Foton] -> KdTree Float Foton
createKD [Foton]
notkdt -- Crea el kdtree

      let cams :: [Camara]
cams = Camara -> Int -> Float -> [Camara]
mulCam Camara
camara Int
8 Float
0.2-- El primer número indica el número de muestras que se toman desde la cámara, el segundo el radio de apertura
          rayitos :: [[Ray]]
rayitos = (Camara -> [Ray]) -> [Camara] -> [[Ray]]
forall a b. (a -> b) -> [a] -> [b]
map (\Camara
camara -> Int
-> Int
-> Int
-> Int
-> Camara
-> Float
-> Float
-> Int
-> StdGen
-> [Ray]
generateRaysForPixels (Int
maxNInt -> Int -> Int
forall a. Num a => a -> a -> a
*Int
etapasY) Int
etapasX Int
n' Int
etapaX Camara
camara (Float
pixFloat -> Float -> Float
forall a. Num a => a -> a -> a
*Float
aspectR) Float
pix Int
nRay StdGen
gen) [Camara]
cams -- Genera los rayos para cada pixel

          a :: [[RGB]]
a = ([Ray] -> [RGB]) -> [[Ray]] -> [[RGB]]
forall a b. (a -> b) -> [a] -> [b]
map (\[Ray]
rayos -> KdTree Float Foton
-> [Luz] -> Point3D -> Set Shape -> [Ray] -> Int -> [RGB]
listRayPhoton KdTree Float Foton
kdt [Luz]
luces Point3D
cam Set Shape
figuras''' [Ray]
rayos Int
nRay) [[Ray]]
rayitos -- Photon mapping
          -- a = map (\rayos -> listRayToRGB luces figuras rayos gen' nRay) rayitos -- Path tracing
          
          c :: [RGB]
c = [[RGB]] -> [RGB]
mediaLRGB [[RGB]]
a
          fin :: String
fin = (RGB -> String) -> [RGB] -> String
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap RGB -> String
rgbToString (Float -> Float -> [RGB] -> [RGB]
gammaFunc Float
fmx Float
gamma [RGB]
c)
      String -> Int -> Int -> String -> IO ()
writePPM (String
"a" String -> String -> String
forall a. [a] -> [a] -> [a]
++ Int -> String
forall a. Show a => a -> String
show Int
n String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"_" String -> String -> String
forall a. [a] -> [a] -> [a]
++ Int -> String
forall a. Show a => a -> String
show Int
etapaY String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"_" String -> String -> String
forall a. [a] -> [a] -> [a]
++ Int -> String
forall a. Show a => a -> String
show Int
etapaX String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
".ppm") (Float -> Int
forall a b. (RealFrac a, Integral b) => a -> b
round (Float -> Int) -> Float -> Int
forall a b. (a -> b) -> a -> b
$ Float
pixFloat -> Float -> Float
forall a. Num a => a -> a -> a
*Float
aspectR) (Float -> Int
forall a b. (RealFrac a, Integral b) => a -> b
round Float
pix) String
fin

      Integer
end <- IO Integer
getCPUTime
      let diff :: Float
diff = Integer -> Float
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Integer
end Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
- Integer
start) Float -> Float -> Float
forall a. Fractional a => a -> a -> a
/ (Float
10Float -> Integer -> Float
forall a b. (Num a, Integral b) => a -> b -> a
^Integer
12) :: Float
      String -> IO ()
putStrLn (String -> IO ()) -> String -> IO ()
forall a b. (a -> b) -> a -> b
$ String
"Tiempo de procesado de la imagen: " String -> String -> String
forall a. [a] -> [a] -> [a]
++ Float -> String
forall a. Show a => a -> String
show Float
diff String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" segundos"

      String -> IO ()
traceEventIO String
"END"
    [] -> do
      StdGen
gen <- IO StdGen
forall (m :: * -> *). MonadIO m => m StdGen
newStdGen
      Integer
start <- IO Integer
getCPUTime
      let !kdt :: DList Foton
kdt = Float
-> DList Foton
-> Int
-> Int
-> Set Shape
-> [Luz]
-> StdGen
-> Int
-> DList Foton
createPhoton ([Luz] -> Float
sumFlLuz [Luz]
luces) ([Foton] -> DList Foton
forall a. [a] -> DList a
DL.fromList []) Int
0 (Float -> Int
forall a b. (RealFrac a, Integral b) => a -> b
round Float
n) Set Shape
figuras''' [Luz]
luces StdGen
gen Int
nRebotes
      Int -> IO ()
forall a. Show a => a -> IO ()
print (Int -> IO ()) -> Int -> IO ()
forall a b. (a -> b) -> a -> b
$ DList Foton -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length DList Foton
kdt
      Integer
end <- IO Integer
getCPUTime
      let diff :: Float
diff = Integer -> Float
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Integer
end Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
- Integer
start) Float -> Float -> Float
forall a. Fractional a => a -> a -> a
/ (Float
10Float -> Integer -> Float
forall a b. (Num a, Integral b) => a -> b -> a
^Integer
12) :: Float
      String -> IO ()
putStrLn (String -> IO ()) -> String -> IO ()
forall a b. (a -> b) -> a -> b
$ String
"Tiempo de creacion del kdt: " String -> String -> String
forall a. [a] -> [a] -> [a]
++ Float -> String
forall a. Show a => a -> String
show Float
diff String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" segundos"
      String -> DList Foton -> IO ()
forall a. Binary a => String -> DList a -> IO ()
writeObject String
"./kd.bin" DList Foton
kdt
    [Maybe Int]
_ -> do
      String -> IO ()
putStrLn String
"Please provide an integer as the first argument."
      IO ()
forall a. IO a
exitFailure