3

If not,is there any alternative way to implement a natural log component into your smart contract code?

1

As explained by Arvidj, there are no floating point numbers in Michelson (or SmartPy), no exp or log function.

While working with natural numbers, you can implement by hand some examples which may or may not be enough for you. Some examples here: https://smartpy.io/dev/index.html?template=calculator.py, https://smartpy.io/dev/index.html?template=worldCalculator.py

A complete example for you:

import smartpy as sp

class Calculator(sp.Contract):
    def __init__(self):
        self.init(value = 0)

    @sp.entry_point
    def test(self, x):
        self.data.value = self.log2(x)

    @sp.global_lambda
    def log2(x):
        result = sp.local('result', 0)
        y = sp.local('y', x)
        sp.while 1 < y.value:
            result.value += 1
            y.value //= 2
        sp.result(result.value)
        
if "templates" not in __name__:
    @sp.add_test(name = "Calculator")
    def test():
        c1 = Calculator()
        scenario = sp.test_scenario()
        scenario += c1
        scenario += c1.test(1000)
        scenario.verify(c1.data.value == 9)

EDIT. Adding a fixed precision implementation in SmartPy.

https://smartpy.io/dev/index.html?template=fixed_precision.py

| improve this answer | |
  • The link to the fixed precision contract is dead. Could you please update it ? Tx! – Ezy Jul 13 at 10:58
  • It has been fixed. – FFF Jul 13 at 11:03
4

You have to do it manually... Here's one approach for compute log(x) assuming you are representing x as a fraction

  1. find integer m through binary search such that 2^m <= x < 2^(m+1) (m may be negative)
  2. let m' = m + (1 if |x/2^(m+1)-1| < |x/2^m-1| else 0) (the closests of m or m+1)
  3. let x' = x / 2^m', note that |x'-1| < 1/3 and log(x) = log(2^m' x') = m' log(2) + log(x')
  4. let y = (1-x')/(1+x'), note that -1/7 < y < 1/5
  5. log(x') ~= - 2 y - 2 y^3 / 3
| improve this answer | |
  • It's not obvious to me that the question was about floating point numbers represented here as fractions or simply integers. – FFF Jul 9 at 18:08
3

I have a contract for binary log that uses few multiplications and can be adjusted for any fixed point precision: https://github.com/Sophia-Gold/michelson/blob/master/log2fix.tz. I don't think it can be written in SmartPy because last I checked it lacks shifts. Depending on your needs you could use this with change of base or Arthur's method.

| improve this answer | |
  • 2
    Shifts are handled by SmartPy as in Python (since last February). << and >>. Should be properly documented (but are not as of today, which is a shame). – FFF Jul 9 at 18:04
  • Do you have the ligo version of this michelson script?Would be helpful to understand it better – George Mathew Kanianthara Jul 9 at 19:43
  • @GeorgeMathewKanianthara don't have a ligo version, but the article linked in the comment explains how it works. – Sophia Gold Jul 9 at 22:39
  • 2
    A SmartPy version with the test version (we had to fix the interpreter for shifts). smartpy.io/dev/index.html?template=fixed_precision.py – FFF Jul 10 at 12:40
0

There is no such instruction in Michelson, so probably the same goes for SmartPy. Furthermore, Michelson does not having floating point values. You could implement some version of natural log yourself using repeated divisions, however, precision will suffer. Also, note that this can be costly in gas.

One option is to have the contract take the contract take in parameter the exponent calculated off-chain, and then have the contract verify that the exponent is indeed correct. Instead of (in pseudocode):

   def contract(some_parameter):
       exponent = nl(some_parameter)

have

   def contract(expected_exponent, some_parameter):
       assert e^expected_exponent = some_parameter

but again, you will turn into the issue that exponentiation is not available in Michelson (but which you could implement with repeated multiplications), and nor are floating points values.

We can perhaps help you better if you give more context to the issue you want to resolve?

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.