Skip to content

Commit c5fc0ae

Browse files
committed
feat: add Logarithmic wrapper for modeling logarithmic complexity
Add a new Logarithmic newtype wrapper in ExMemoryUsage that transforms size measures logarithmically. This enables linear cost models to effectively capture O(log n) runtime behavior by measuring log(size) instead of size directly. The wrapper computes max(1, floor(log2(size) + 1)) from any wrapped ExMemoryUsage instance, making it composable with existing size measures like ValueOuterOrMaxInner for operations with logarithmic complexity. This infrastructure supports proper costing of Value builtins like lookupCoin which has O(log max(m, k)) complexity.
1 parent b8286e5 commit c5fc0ae

File tree

1 file changed

+24
-0
lines changed

1 file changed

+24
-0
lines changed

plutus-core/plutus-core/src/PlutusCore/Evaluation/Machine/ExMemoryUsage.hs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ module PlutusCore.Evaluation.Machine.ExMemoryUsage
1414
, IntegerCostedLiterally(..)
1515
, ValueTotalSize(..)
1616
, ValueOuterOrMaxInner(..)
17+
, Logarithmic(..)
1718
) where
1819

1920
import PlutusCore.Crypto.BLS12_381.G1 as BLS12_381.G1
@@ -391,6 +392,29 @@ instance ExMemoryUsage ValueOuterOrMaxInner where
391392
where
392393
size = Map.size (Value.unpack v) `max` Value.maxInnerSize v
393394

395+
{-| A wrapper that applies a logarithmic transformation to another size measure.
396+
This is useful for modeling operations with logarithmic complexity, where the cost
397+
depends on log(n) where n is the size measure from the wrapped newtype.
398+
399+
For example, @Logarithmic ValueOuterOrMaxInner@ can be used to model operations
400+
that are O(log max(m, k)) where m is the number of policies and k is the max tokens
401+
per policy.
402+
403+
The memory usage is calculated as: @max 1 (floor (log2 size + 1))@ where size comes
404+
from the wrapped newtype's ExMemoryUsage instance.
405+
-}
406+
newtype Logarithmic n = Logarithmic { unLogarithmic :: n }
407+
408+
instance ExMemoryUsage n => ExMemoryUsage (Logarithmic n) where
409+
memoryUsage (Logarithmic wrapped) =
410+
case memoryUsage wrapped of
411+
CostRose size _ ->
412+
let sizeInteger :: Integer
413+
sizeInteger = fromSatInt size
414+
logSize = I# (integerLog2# sizeInteger)
415+
in singletonRose $ max 1 (fromIntegral (logSize + 1))
416+
{-# INLINE memoryUsage #-}
417+
394418
{- Note [Costing constant-size types]
395419
The memory usage of each of the BLS12-381 types is constant, so we may be able
396420
to optimise things a little by ensuring that we don't re-compute the size of

0 commit comments

Comments
 (0)