【问题标题】:WAT: more elegant way to achieve Horner's methodWAT:更优雅的方式来实现霍纳的方法
【发布时间】:2022-01-23 23:16:02
【问题描述】:

我在WAT 中申请Horner's Method。用我自己的任意语法表达,算法基本是:

horner(baseValue, T1, T2, T3) {
  return T1+(T2*baseValue²)+(T3*baseValue³)
}

T1, T2, T3 可任意扩展:T4T5 等可能会被调用。理想情况下,如果函数的 T 参数是可变的,那就太好了。换句话说,如果我可以使用 WAT 等效项,那就太好了:

horner(baseValue, ...T)

然后按照commenthol 在出色的astronomia 库中所做的事情做一些事情:

let i = T.length - 1
  let y = c[T]
  while (i > 0) {
    i--
    y = y * x + T[i]
  }
  return y

据我所知,没有 WAT 等效于可变参数。我认为我需要以不同的方式处理算法。

这是我能想到的性能最高的函数:

(func $horner
    ;;     0
    (param $x f64)
    ;;     1   2   3   4   5
    ;;     +   *x  *x2 *x3 *x4 
    (param f64 f64 f64 f64 f64)
    (result f64)

    ;; x to the fourth
    local.get 5
    local.get $x
    local.get $x
    local.get $x
    local.get $x
    f64.mul
    f64.mul
    f64.mul
    f64.mul

    ;; x to the third
    local.get 4
    local.get $x
    local.get $x
    local.get $x
    f64.mul
    f64.mul
    f64.mul

    ;; x squared
    local.get 3
    local.get $x
    local.get $x
    f64.mul
    f64.mul

    ;; x to the first
    local.get 2
    local.get $x
    f64.mul

    ;; add all the terms together
    local.get 1
    f64.add
    f64.add
    f64.add
    f64.add

)

我可以根据需要扩展参数集并在不需要参数时传递零,但这也会导致一些不需要的计算。我认为最好的方法是为 2 个参数创建 horner2,为 3 个参数创建 horner3,依此类推。

有没有更优雅、同样性能的方法?

【问题讨论】:

    标签: webassembly


    【解决方案1】:

    WebAssembly 函数没有可变数量的参数。

    我看到的一个可能的解决方案是使用线性内存来完成这项工作:将参数存储到线性内存中,将地址传递给这个列表/数组和元素的数量作为参数,然后将所有值循环到线性内存(从最后到第一个)进行数学运算并返回最终值。要拥有任何类型的类型,您可以将预期类型作为 u32 值提供并从内存中动态读取此类型是什么。

    因为调用者能够将所有参数压入堆栈,所以这意味着您可以从堆栈中弹出(顶部是最后一个值),而不是调用此函数并将参数作为参数传递数学,从堆栈中再弹出一个值,依此类推。最后,在使用所有这些值之后,您将获得最终结果。这里的问题是你必须为每个调用者“内联”这个逻辑。要拥有任何类型的类型,您还必须关注每个值的类型,或者为所有值设置一种类型,并从堆栈中动态弹出应该存在的内容。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-03-30
      • 1970-01-01
      • 2015-06-22
      • 1970-01-01
      • 2012-12-16
      • 1970-01-01
      • 2013-06-28
      相关资源
      最近更新 更多