-
Notifications
You must be signed in to change notification settings - Fork 483
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
5 changed files
with
153 additions
and
39 deletions.
There are no files selected for viewing
2 changes: 2 additions & 0 deletions
2
plutus-tx-plugin/test/Recursion/9.6/length-unrolled.budget.golden
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
({cpu: 4580180 | ||
| mem: 22420}) |
1 change: 1 addition & 0 deletions
1
plutus-tx-plugin/test/Recursion/9.6/length-unrolled.eval.golden
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
(con integer 10) |
19 changes: 19 additions & 0 deletions
19
plutus-tx-plugin/test/Recursion/9.6/length-unrolled.uplc.golden
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
(program | ||
1.1.0 | ||
((\s -> s s) | ||
(\s ds -> | ||
case | ||
ds | ||
[ 0 | ||
, (\ds xs -> | ||
addInteger | ||
1 | ||
(case | ||
xs | ||
[ 0 | ||
, (\ds xs -> | ||
addInteger | ||
1 | ||
(case | ||
xs | ||
[0, (\ds xs -> addInteger 1 (s s xs))])) ])) ]))) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,37 +1,88 @@ | ||
{-# LANGUAGE BlockArguments #-} | ||
{-# LANGUAGE TemplateHaskell #-} | ||
|
||
-- | Utilities for space-time tradeoff, such as recursion unrolling. | ||
module PlutusTx.Optimize.SpaceTime (peel) where | ||
module PlutusTx.Optimize.SpaceTime (peel, unroll) where | ||
|
||
import Prelude | ||
|
||
import Language.Haskell.TH.Syntax.Compat qualified as TH | ||
import PlutusTx.Function (fix) | ||
import Prelude | ||
|
||
{-| Given @n@, and the functional (or algebra) for a recursive function, peel @n@ layers | ||
{-| Given @n@, and the step function for a recursive function, peel @n@ layers | ||
off of the recursion. | ||
For example @peel 2 (\f xs -> case xs of [] -> 0; (_:ys) -> 1 + f ys)@ yields the | ||
equivalence of the following function: | ||
For example @peel 3 (\self -> [[| \case [] -> 0; _ : ys -> 1 + self ys||])@ | ||
yields the equivalence of the following function: | ||
@ | ||
lengthPeeled :: [a] -> a | ||
lengthPeeled xs = case xs of | ||
[] -> 0 | ||
y:ys -> 1 + case ys of | ||
[] -> 0 | ||
z:zs -> 1 + case zs of | ||
[] -> 0 | ||
w:ws -> 1 + length ws | ||
lengthPeeled :: [a] -> a | ||
lengthPeeled xs = | ||
case xs of -- first recursion step | ||
[] -> 0 | ||
_ : ys -> 1 + | ||
case ys of -- second recursion step | ||
[] -> 0 | ||
_ : zs -> 1 + | ||
case zs of -- third recursion step | ||
[] -> 0 | ||
_ : ws -> 1 + | ||
( fix \self qs -> -- rest of recursion steps in a tight loop | ||
case qs of | ||
[] -> 0 | ||
_ : ts -> 1 + self ts | ||
) ws | ||
@ | ||
where @length@ is the regular recursive definition. | ||
-} | ||
peel | ||
:: forall a b | ||
. Int | ||
-- ^ How many recursion steps to move outside of the recursion loop. | ||
-> (TH.SpliceQ (a -> b) -> TH.SpliceQ (a -> b)) | ||
{- ^ Function that given a continuation splice returns | ||
a splice representing a single recursion step calling this continuation. | ||
-} | ||
-> TH.SpliceQ (a -> b) | ||
peel 0 f = [||fix (\g -> $$(f [||g||]))||] | ||
peel 0 f = [||fix \self -> $$(f [||self||])||] | ||
peel n f | ||
| n > 0 = f (peel (n - 1) f) | ||
| otherwise = error $ "PlutusTx.Optimize.SpaceTime.peel: negative n: " <> show n | ||
|
||
{-| Given @n@, and the step function for a recursive function, | ||
unroll recursion @n@ layers at a time | ||
For example @unroll 3 (\self -> [|| \case [] -> 0; _ : ys -> 1 + self ys ||])@ | ||
yields the equivalence of the following function: | ||
@ | ||
lengthUnrolled :: [a] -> a | ||
lengthUnrolled = | ||
fix \self xs -> -- beginning of the recursion "loop" | ||
case xs of -- first recursion step | ||
[] -> 0 | ||
_ : ys -> 1 + | ||
case ys of -- second recursion step | ||
[] -> 0 | ||
_ : zs -> 1 + | ||
case zs of -- third recursion step | ||
[] -> 0 | ||
_ : ws -> 1 + self ws -- end of the "loop" | ||
@ | ||
-} | ||
unroll | ||
:: forall a b | ||
. Int | ||
-- ^ How many recursion steps to perform inside the recursion loop. | ||
-> (TH.SpliceQ (a -> b) -> TH.SpliceQ (a -> b)) | ||
{- ^ Function that given a continuation splice returns | ||
a splice representing a single recursion step calling this continuation. | ||
-} | ||
-> TH.SpliceQ (a -> b) | ||
unroll n f = [||fix \self -> $$(nTimes n f [||self||])||] | ||
|
||
-- | Apply a function @n@ times to a given value. | ||
nTimes :: Int -> (a -> a) -> (a -> a) | ||
nTimes 0 _ = id | ||
nTimes 1 f = f | ||
nTimes n f = f . nTimes (n - 1) f |