代码之家  ›  专栏  ›  技术社区  ›  d33tah

为什么从C(来自Wikipedia)移植的Hilbert曲线实现似乎失败了[[关闭]

  •  -2
  • d33tah  · 技术社区  · 6 年前

    我找到了下面的绘图代码 Hilbert Curves 在维基百科上:

    //convert (x,y) to d
    int xy2d (int n, int x, int y) {
        int rx, ry, s, d=0;
        for (s=n/2; s>0; s/=2) {
            rx = (x & s) > 0;
            ry = (y & s) > 0;
            d += s * s * ((3 * rx) ^ ry);
            rot(s, &x, &y, rx, ry);
        }
        return d;
    }
    
    //convert d to (x,y)
    void d2xy(int n, int d, int *x, int *y) {
        int rx, ry, s, t=d;
        *x = *y = 0;
        for (s=1; s<n; s*=2) {
            rx = 1 & (t/2);
            ry = 1 & (t ^ rx);
            rot(s, x, y, rx, ry);
            *x += s * rx;
            *y += s * ry;
            t /= 4;
        }
    }
    
    //rotate/flip a quadrant appropriately
    void rot(int n, int *x, int *y, int rx, int ry) {
        if (ry == 0) {
            if (rx == 1) {
                *x = n-1 - *x;
                *y = n-1 - *y;
            }
    
            //Swap x and y
            int t  = *x;
            *x = *y;
            *y = t;
        }
    }
    

    我把它放进 c2rust.com

    #![allow(dead_code,
             mutable_transmutes,
             non_camel_case_types,
             non_snake_case,
             non_upper_case_globals,
             unused_mut)]
    #![feature(libc)]
    extern crate libc;
    // rotate/flip a quadrant appropriately
    #[no_mangle]
    pub unsafe extern "C" fn rot(mut n: libc::c_int,
                                 mut x: *mut libc::c_int,
                                 mut y: *mut libc::c_int,
                                 mut rx: libc::c_int,
                                 mut ry: libc::c_int)
                                 -> () {
        if ry == 0i32 {
            if rx == 1i32 {
                *x = n - 1i32 - *x;
                *y = n - 1i32 - *y
            }
            // Swap x and y
            let mut t: libc::c_int = *x;
            *x = *y;
            *y = t
        };
    }
    // convert (x,y) to d
    #[no_mangle]
    pub unsafe extern "C" fn xy2d(mut n: libc::c_int,
                                  mut x: libc::c_int,
                                  mut y: libc::c_int)
                                  -> libc::c_int {
        let mut rx: libc::c_int = 0;
        let mut ry: libc::c_int = 0;
        let mut s: libc::c_int = 0;
        let mut d: libc::c_int = 0i32;
        s = n / 2i32;
        while s > 0i32 {
            rx = (x & s > 0i32) as libc::c_int;
            ry = (y & s > 0i32) as libc::c_int;
            d += s * s * (3i32 * rx ^ ry);
            rot(s, &mut x, &mut y, rx, ry);
            s /= 2i32
        }
        return d;
    }
    // convert d to (x,y)
    #[no_mangle]
    pub unsafe extern "C" fn d2xy(mut n: libc::c_int,
                                  mut d: libc::c_int,
                                  mut x: *mut libc::c_int,
                                  mut y: *mut libc::c_int)
                                  -> () {
        let mut rx: libc::c_int = 0;
        let mut ry: libc::c_int = 0;
        let mut s: libc::c_int = 0;
        let mut t: libc::c_int = d;
        *y = 0i32;
        *x = *y;
        s = 1i32;
        while s < n {
            rx = 1i32 & t / 2i32;
            ry = 1i32 & (t ^ rx);
            rot(s, x, y, rx, ry);
            *x += s * rx;
            *y += s * ry;
            t /= 4i32;
            s *= 2i32
        }
    }
    
    fn main() {
        let mut x: libc::c_int = 0;
        let mut y: libc::c_int = 0;
        let d: libc::c_int = 10;
        unsafe {
            for n in 1..10 {
                d2xy(n, d, &mut x, &mut y);
                println!("n={}, x={}, y={}", n, x, y);
            }
        }
    }
    

       Compiling x v0.1.0 (file:///tmp/x)
    warning: value assigned to `rx` is never read                            ] 0/1: x                                                                                                                
      --> src/main.rs:34:13
       |
    34 |     let mut rx: libc::c_int = 0;
       |             ^^
       |
       = note: #[warn(unused_assignments)] on by default
    
    warning: value assigned to `ry` is never read
      --> src/main.rs:35:13
       |
    35 |     let mut ry: libc::c_int = 0;
       |             ^^
    
    warning: value assigned to `s` is never read
      --> src/main.rs:36:13
       |
    36 |     let mut s: libc::c_int = 0;
       |             ^
    
    warning: value assigned to `rx` is never read
      --> src/main.rs:55:13
       |
    55 |     let mut rx: libc::c_int = 0;
       |             ^^
    
    warning: value assigned to `ry` is never read
      --> src/main.rs:56:13
       |
    56 |     let mut ry: libc::c_int = 0;
       |             ^^
    
    warning: value assigned to `s` is never read
      --> src/main.rs:57:13
       |
    57 |     let mut s: libc::c_int = 0;
       |             ^
    
        Finished dev [unoptimized + debuginfo] target(s) in 0.25s                                                                                                                                    
         Running `target/debug/x`
    n=1, x=0, y=0
    n=2, x=1, y=1
    n=3, x=3, y=3
    n=4, x=3, y=3
    n=5, x=3, y=3
    n=6, x=3, y=3
    n=7, x=3, y=3
    n=8, x=3, y=3
    n=9, x=3, y=3
    

    我绝对没想到不同的N会有重复的坐标。可能出了什么问题?下面是用于比较的C测试代码:

    int main() {
        int n=32, d=0, x=0, y=0;
        for (d=0; d<10; d++) {
            d2xy(n, d, &x, &y);
            printf("d=%d, x=%d, y=%d\n", d, x, y);
        }
    }
    

    以及预期输出(由C生成):

    d=0, x=0, y=0
    d=1, x=0, y=1
    d=2, x=1, y=1
    d=3, x=1, y=0
    d=4, x=2, y=0
    d=5, x=3, y=0
    d=6, x=3, y=1
    d=7, x=2, y=1
    d=8, x=2, y=2
    d=9, x=3, y=2
    
    1 回复  |  直到 6 年前
        1
  •  5
  •   DK.    6 年前

    如果你改变测试代码,你自然会得到不同的输出。原来的C测试代码修复了 n 而且各不相同 d ; 你修好了吗 和变化 .

    fn main() {
        let mut x: libc::c_int = 0;
        let mut y: libc::c_int = 0;
        let d: libc::c_int = 10;
        unsafe {
            for n in 1..10 {
                d2xy(n, d, &mut x, &mut y);
                println!("n={}, x={}, y={}", n, x, y);
            }
        }
    }
    
    推荐文章