<commit_before>extern crate polydraw;

use polydraw::os::win;
use polydraw::os::wgl;
use polydraw::os::gl;

fn main() {
   let width: usize = 1280;
   let height: usize = 720;

   let window = win::Window::create(width, height, "Win Min", "WinMinClass");
   window.show_normal();

   let dc = window.dc();
   println!("DC: {:?}", dc);

   match wgl::init_pixel_format(dc) {
      Ok(_) => {},
      Err(e) => {
         panic!(e.description);
      }
   };

   let context = match wgl::Context::create(dc) {
      Ok(context) => context,
      Err(e) => {
         panic!(e.description);
      }
   };

   println!("RC: {:?}", context.rc);

   gl::load(wgl::Loader::new());

   loop {
      let message = match win::Message::get() {
         Some(message) => message,
         None => break
      };

      message.translate();
      message.dispatch();

      gl::clear_color(0.0, 0.7, 1.0, 1.0);
      gl::clear();
      gl::flush();

      wgl::swap_buffers(dc);
   }
}
<commit_msg>Creating a GL texture and framebuffer<commit_after>extern crate polydraw;

use polydraw::os::win;
use polydraw::os::wgl;
use polydraw::os::gl;

fn main() {
   let width: usize = 1280;
   let height: usize = 720;

   let window = win::Window::create(width, height, "Win Min", "WinMinClass");
   window.show_normal();

   let dc = window.dc();
   println!("DC: {:?}", dc);

   match wgl::init_pixel_format(dc) {
      Ok(_) => {},
      Err(e) => {
         panic!(e.description);
      }
   };

   let context = match wgl::Context::create(dc) {
      Ok(context) => context,
      Err(e) => {
         panic!(e.description);
      }
   };

   println!("RC: {:?}", context.rc);

   gl::load(wgl::Loader::new());

   let texture = gl::Texture::new(width, height);

   println!("GL texture ................ : {:?}", texture.name);

   let framebuffer = gl::Framebuffer::new(&texture);

   println!("GL framebuffer ............ : {:?}", framebuffer.name);

   loop {
      let message = match win::Message::get() {
         Some(message) => message,
         None => break
      };

      message.translate();
      message.dispatch();

      gl::clear_color(0.0, 0.7, 1.0, 1.0);
      gl::clear();
      gl::flush();

      wgl::swap_buffers(dc);
   }
}
<|endoftext|>


<commit_before>use criterion::*;
use rand::{Rng, SeedableRng};
use rand_chacha::ChaChaRng;
use rav1e::bench::frame::*;

fn init_plane_u8(width: usize, height: usize) -> Plane<u8> {
  let mut ra = ChaChaRng::from_seed([0; 32]);
  let data: Vec<u8> = (0..(width * height)).map(|_| ra.gen()).collect();
  Plane::from_slice(&data, width)
}

fn init_plane_u16(width: usize, height: usize) -> Plane<u16> {
  let mut ra = ChaChaRng::from_seed([0; 32]);
  let data: Vec<u16> = (0..(width * height)).map(|_| ra.gen()).collect();
  Plane::from_slice(&data, width)
}

pub fn downsample_8bit(c: &mut Criterion) {
  let input = init_plane_u8(1920, 1080);
  c.bench_function("downsample_8bit", move |b| {
    b.iter(|| {
      let _ = input.downsampled(960, 540);
    })
  });
}

pub fn downsample_odd(c: &mut Criterion) {
  let input = init_plane_u8(1919, 1079);
  c.bench_function("downsample_odd", move |b| {
    b.iter(|| {
      let _ = input.downsampled(960, 540);
    })
  });
}

pub fn downsample_10bit(c: &mut Criterion) {
  let input = init_plane_u16(1920, 1080);
  c.bench_function("downsample_10bit", move |b| {
    b.iter(|| {
      let _ = input.downsampled(960, 540);
    })
  });
}

criterion_group!(plane, downsample_8bit, downsample_odd, downsample_10bit);
<commit_msg>Fix assert failure in bench of downsample_odd<commit_after>use criterion::*;
use rand::{Rng, SeedableRng};
use rand_chacha::ChaChaRng;
use rav1e::bench::frame::*;

fn init_plane_u8(width: usize, height: usize) -> Plane<u8> {
  let mut ra = ChaChaRng::from_seed([0; 32]);
  let data: Vec<u8> = (0..(width * height)).map(|_| ra.gen()).collect();
  let out = Plane::from_slice(&data, width);
  if out.cfg.width % 2 == 0 && out.cfg.height % 2 == 0 {
    out
  } else {
    let xpad = out.cfg.width % 2;
    let ypad = out.cfg.height % 2;
    let mut padded =
      Plane::new(out.cfg.width, out.cfg.height, 0, 0, xpad, ypad);
    let mut padded_slice = padded.mut_slice(PlaneOffset { x: 0, y: 0 });
    for (dst_row, src_row) in padded_slice.rows_iter_mut().zip(out.rows_iter())
    {
      dst_row[..out.cfg.width].copy_from_slice(&src_row[..out.cfg.width]);
    }
    padded
  }
}

fn init_plane_u16(width: usize, height: usize) -> Plane<u16> {
  let mut ra = ChaChaRng::from_seed([0; 32]);
  let data: Vec<u16> = (0..(width * height)).map(|_| ra.gen()).collect();
  Plane::from_slice(&data, width)
}

pub fn downsample_8bit(c: &mut Criterion) {
  let input = init_plane_u8(1920, 1080);
  c.bench_function("downsample_8bit", move |b| {
    b.iter(|| {
      let _ = input.downsampled(input.cfg.width, input.cfg.height);
    })
  });
}

pub fn downsample_odd(c: &mut Criterion) {
  let input = init_plane_u8(1919, 1079);
  c.bench_function("downsample_odd", move |b| {
    b.iter(|| {
      let _ = input.downsampled(input.cfg.width, input.cfg.height);
    })
  });
}

pub fn downsample_10bit(c: &mut Criterion) {
  let input = init_plane_u16(1920, 1080);
  c.bench_function("downsample_10bit", move |b| {
    b.iter(|| {
      let _ = input.downsampled(input.cfg.width, input.cfg.height);
    })
  });
}

criterion_group!(plane, downsample_8bit, downsample_odd, downsample_10bit);
<|endoftext|>


<commit_before>extern crate rs6502;
extern crate sdl2;
extern crate vm;

mod ship;

use std::path::Path;

use sdl2::event::Event;
use sdl2::keyboard::Keycode;
use sdl2::image::LoadTexture;
use sdl2::pixels::Color;
use sdl2::rect::Rect;
use sdl2::render::TextureQuery;

use rs6502::{Assembler, Cpu};
use vm::VirtualMachine;

const FPS_STEP: u32 = 1000 / 60;

fn main() {

    let bytecode = assemble("level.asm");
    let cpu = init_cpu(&bytecode);
    let mut vm = VirtualMachine::new(cpu, 0xC000, 150);

    let sdl_context = sdl2::init().unwrap();
    let ttf_context = sdl2::ttf::init().unwrap();
    let video_subsystem = sdl_context.video().unwrap();

    let window = video_subsystem.window("Hakka", 400, 720)
        .position_centered()
        .build()
        .unwrap();

    let mut renderer = window.renderer()
        .accelerated()
        .build()
        .unwrap();

    let ship_texture = renderer.load_texture(Path::new("ship.png")).unwrap();
    let ship_flame_texture = renderer.load_texture(Path::new("ship-flame.png")).unwrap();

    let mut win_font = ttf_context.load_font(Path::new("FantasqueSansMono-Bold.ttf"), 64).unwrap();
    win_font.set_style(sdl2::ttf::STYLE_BOLD);

    let mut finish_font = ttf_context.load_font(Path::new("FantasqueSansMono-Bold.ttf"), 64)
        .unwrap();
    finish_font.set_style(sdl2::ttf::STYLE_BOLD);

    let win_message_surface = win_font.render("You win!")
        .blended(Color::RGBA(0, 153, 192, 255))
        .unwrap();
    let finish_banner_surface = finish_font.render("FINISH")
        .blended_wrapped(Color::RGBA(0, 0, 0, 255), 56)
        .unwrap();
    let win_message_texture = renderer.create_texture_from_surface(&win_message_surface)
        .unwrap();
    let finish_banner_texture = renderer.create_texture_from_surface(&finish_banner_surface)
        .unwrap();
    let mut events = sdl_context.event_pump().unwrap();

    let mut level_complete = false;
    let mut ship = ship::Ship::new(ship_texture, ship_flame_texture);
    let mut last_fps = 0;
    let mut monitor_last = 0;
    let TextureQuery { width: win_width, height: win_height, .. } = win_message_texture.query();
    let TextureQuery { width: finish_width, height: finish_height, .. } =
        finish_banner_texture.query();

    'running: loop {

        for event in events.poll_iter() {
            match event {
                Event::Quit { .. } => break 'running,
                Event::KeyDown { keycode: Option::Some(Keycode::Up), .. } => {
                    vm.cpu.memory[0x04] = 38;
                }
                Event::KeyDown { keycode: Option::Some(Keycode::Down), .. } => {
                    vm.cpu.memory[0x04] = 40;
                }
                Event::KeyUp { keycode: Option::Some(Keycode::Up), .. } => {
                    vm.cpu.memory[0x04] = 0;
                }
                Event::KeyUp { keycode: Option::Some(Keycode::Down), .. } => {
                    vm.cpu.memory[0x04] = 0;
                }
                Event::KeyDown { keycode: Option::Some(Keycode::Escape), .. } => break 'running,
                _ => (),
            }
        }

        if !level_complete {
            vm.try_execute_command();
            ship.process(&vm.cpu.memory[..]);

            // Pull the ship back so it can't go past a certain spot
            if ship.y <= 0x190 && ship.y >= 0x100 && vm.cpu.memory[0x04] != 0 {
                vm.cpu.memory[0x02] = 0x90;
                vm.cpu.memory[0x03] = 0x01;
            }
        }

        let now = sdl_context.timer().unwrap().ticks();
        let delta = now - last_fps;
        if delta < FPS_STEP {
            sdl_context.timer().unwrap().delay(FPS_STEP - delta);
        } else {
            vm.cycle();
            if !vm.cpu.flags.interrupt_disabled {
                renderer.clear();
                renderer.set_draw_color(Color::RGB(0, 144, 192));
                renderer.fill_rect(Rect::new(0, 0, 400, 120)).unwrap();
                renderer.set_draw_color(Color::RGB(0, 0, 0));
                renderer.copy(&finish_banner_texture,
                          None,
                          Some(Rect::new(100, 25, finish_width, finish_height)))
                    .unwrap();
                if vm.cpu.memory[0x07] > 0 {
                    ship.render_flame(&mut renderer);
                }
                ship.render(&mut renderer);
                if ship.y <= 0x8C {
                    level_complete = true;
                    renderer.copy(&win_message_texture,
                              None,
                              Some(Rect::new(75, 200, win_width, win_height)))
                        .unwrap();
                }
                renderer.present();
                last_fps = now;
            }
        }

        // Dump the CPU memory at 1 second intervals if the monitor is enabled
        let delta = now - monitor_last;
        if delta > 1000 && vm.monitor.enabled {
            vm.dump_memory();
            monitor_last = now;
        }
    }
}

fn assemble<P>(path: P) -> Vec<u8>
    where P: AsRef<Path>
{
    let mut assembler = Assembler::new();
    assembler.assemble_file(path, 0xC000).unwrap()
}

fn init_cpu(bytecode: &[u8]) -> Cpu {
    let mut cpu = Cpu::new();
    cpu.load(&bytecode[..], None).unwrap();
    cpu.flags.interrupt_disabled = false;

    cpu.memory[0x00] = 0x90;
    cpu.memory[0x02] = 0xFF;
    cpu.memory[0x03] = 0x01;
    cpu.memory[0x05] = 0x05;
    cpu.memory[0x06] = 0x00;

    cpu
}<commit_msg>Convert the Win message<commit_after>extern crate rs6502;
extern crate sdl2;
extern crate vm;

mod ship;

use std::path::Path;

use sdl2::event::Event;
use sdl2::keyboard::Keycode;
use sdl2::image::LoadTexture;
use sdl2::pixels::Color;
use sdl2::rect::Rect;
use sdl2::render::TextureQuery;

use rs6502::{Assembler, Cpu};
use vm::VirtualMachine;

const FPS_STEP: u32 = 1000 / 60;

fn main() {

    let bytecode = assemble("level.asm");
    let cpu = init_cpu(&bytecode);
    let mut vm = VirtualMachine::new(cpu, 0xC000, 150);

    let sdl_context = sdl2::init().unwrap();
    let ttf_context = sdl2::ttf::init().unwrap();
    let video_subsystem = sdl_context.video().unwrap();

    let window = video_subsystem.window("Hakka", 400, 720)
        .position_centered()
        .build()
        .unwrap();

    let mut renderer = window.renderer()
        .accelerated()
        .build()
        .unwrap();

    let ship_texture = renderer.load_texture(Path::new("ship.png")).unwrap();
    let ship_flame_texture = renderer.load_texture(Path::new("ship-flame.png")).unwrap();

    let mut win_font = ttf_context.load_font(Path::new("FantasqueSansMono-Bold.ttf"), 64).unwrap();
    win_font.set_style(sdl2::ttf::STYLE_BOLD);

    let mut finish_font = ttf_context.load_font(Path::new("FantasqueSansMono-Bold.ttf"), 64)
        .unwrap();
    finish_font.set_style(sdl2::ttf::STYLE_BOLD);

    let win_message_surface = win_font.render("PASSED")
        .blended(Color::RGBA(0, 0, 0, 255))
        .unwrap();
    let finish_banner_surface = finish_font.render("FINISH")
        .blended_wrapped(Color::RGBA(0, 0, 0, 255), 56)
        .unwrap();
    let win_message_texture = renderer.create_texture_from_surface(&win_message_surface)
        .unwrap();
    let finish_banner_texture = renderer.create_texture_from_surface(&finish_banner_surface)
        .unwrap();
    let mut events = sdl_context.event_pump().unwrap();

    let mut level_complete = false;
    let mut ship = ship::Ship::new(ship_texture, ship_flame_texture);
    let mut last_fps = 0;
    let mut monitor_last = 0;
    let TextureQuery { width: win_width, height: win_height, .. } = win_message_texture.query();
    let TextureQuery { width: finish_width, height: finish_height, .. } =
        finish_banner_texture.query();

    'running: loop {

        for event in events.poll_iter() {
            match event {
                Event::Quit { .. } => break 'running,
                Event::KeyDown { keycode: Option::Some(Keycode::Up), .. } => {
                    vm.cpu.memory[0x04] = 38;
                }
                Event::KeyDown { keycode: Option::Some(Keycode::Down), .. } => {
                    vm.cpu.memory[0x04] = 40;
                }
                Event::KeyUp { keycode: Option::Some(Keycode::Up), .. } => {
                    vm.cpu.memory[0x04] = 0;
                }
                Event::KeyUp { keycode: Option::Some(Keycode::Down), .. } => {
                    vm.cpu.memory[0x04] = 0;
                }
                Event::KeyDown { keycode: Option::Some(Keycode::Escape), .. } => break 'running,
                _ => (),
            }
        }

        if !level_complete {
            vm.try_execute_command();
            ship.process(&vm.cpu.memory[..]);

            // Pull the ship back so it can't go past a certain spot
            if ship.y <= 0x190 && ship.y >= 0x100 && vm.cpu.memory[0x04] != 0 {
                vm.cpu.memory[0x02] = 0x90;
                vm.cpu.memory[0x03] = 0x01;
            }
        }

        let now = sdl_context.timer().unwrap().ticks();
        let delta = now - last_fps;
        if delta < FPS_STEP {
            sdl_context.timer().unwrap().delay(FPS_STEP - delta);
        } else {
            vm.cycle();
            if !vm.cpu.flags.interrupt_disabled {
                renderer.clear();
                renderer.set_draw_color(Color::RGB(0, 144, 192));
                renderer.fill_rect(Rect::new(0, 0, 400, 120)).unwrap();
                if level_complete {
                    renderer.set_draw_color(Color::RGB(0, 255, 0));
                    renderer.fill_rect(Rect::new(0, 300, 400, 120)).unwrap();
                    renderer.copy(&win_message_texture,
                              None,
                              Some(Rect::new(100, 330, win_width, win_height)))
                        .unwrap();
                }
                renderer.set_draw_color(Color::RGB(0, 0, 0));
                renderer.copy(&finish_banner_texture,
                          None,
                          Some(Rect::new(100, 25, finish_width, finish_height)))
                    .unwrap();
                if vm.cpu.memory[0x07] > 0 {
                    ship.render_flame(&mut renderer);
                }
                ship.render(&mut renderer);
                if ship.y <= 0x8C {
                    level_complete = true;
                }
                renderer.present();
                last_fps = now;
            }
        }

        // Dump the CPU memory at 1 second intervals if the monitor is enabled
        let delta = now - monitor_last;
        if delta > 1000 && vm.monitor.enabled {
            vm.dump_memory();
            monitor_last = now;
        }
    }
}

fn assemble<P>(path: P) -> Vec<u8>
    where P: AsRef<Path>
{
    let mut assembler = Assembler::new();
    assembler.assemble_file(path, 0xC000).unwrap()
}

fn init_cpu(bytecode: &[u8]) -> Cpu {
    let mut cpu = Cpu::new();
    cpu.load(&bytecode[..], None).unwrap();
    cpu.flags.interrupt_disabled = false;

    cpu.memory[0x00] = 0x90;
    cpu.memory[0x02] = 0xFF;
    cpu.memory[0x03] = 0x01;
    cpu.memory[0x05] = 0x05;
    cpu.memory[0x06] = 0x00;

    cpu
}<|endoftext|>


<commit_before>use std::ops::{Mul, Add};

use rand::{Rand, Rng, Closed01};
use num::{Float, Zero};

use rblas::{Gemm, Matrix};
use rblas::attribute::Transpose;

use ndarray::{ArrayBase, DataOwned, DataMut};
use ndarray::blas::{BlasArrayViewMut, AsBlas};

use helpers::random01;

pub trait ShapeAsTuple<T> {
    fn shape_as_tuple(&self) -> T;
}

pub type FloatT = f32;

impl<T> ShapeAsTuple<(usize, usize)> for ArrayBase<Vec<T>, (usize, usize)> {
    #[inline]
    fn shape_as_tuple(&self) -> (usize, usize) {
        (self.shape()[0], self.shape()[1])
    }
}

pub type Ix = (usize, usize);
pub type MyMatrix = ArrayBase<Vec<FloatT>, Ix>;

pub struct OrthogonalNMFBlas {
    pub hidden: MyMatrix,
    pub weights: MyMatrix,

    // these hold temporary results during an iteration.
    // kept in this struct to prevent unnecessary memory allocations.
    pub weights_multiplier: MyMatrix,
    pub weights_divisor: MyMatrix,
    pub weights_divisor_reconstruction: MyMatrix,

    pub hidden_multiplier: MyMatrix,
    pub hidden_divisor: MyMatrix,
    pub hidden_divisor_partial: MyMatrix,

    pub gamma: MyMatrix,
}

impl OrthogonalNMFBlas
    // where FloatT: 'a + Float + Mul + Zero + Clone + Gemm,
          // ArrayBase<Vec<FloatT>, (usize, usize)>: 'a + AsBlas<FloatT, ArrayBase<Vec<FloatT>, (usize, usize)>, (usize, usize)> + DataOwned<Elem=FloatT> + DataMut<Elem=FloatT>,
          // BlasArrayViewMut<'a, FloatT, (usize, usize)>: Matrix<FloatT>,
          // Closed01<FloatT>: Rand
{
    pub fn new_random01<R: Rng>(nhidden: usize, nobserved: usize, nsamples: usize, rng: &mut R) -> OrthogonalNMFBlas {
        let mut hidden = MyMatrix::zeros((nhidden, nobserved));
        for x in hidden.iter_mut() {
            *x = random01(rng);
        }

        let mut weights = MyMatrix::zeros((nsamples, nhidden));
        for x in weights.iter_mut() {
            *x = random01(rng);
        }

        Self::new(hidden, weights)
    }

    pub fn new(hidden: MyMatrix, weights: MyMatrix) -> OrthogonalNMFBlas {
        let weights_shape = weights.shape_as_tuple();
        let hidden_shape = hidden.shape_as_tuple();

        let nhidden = hidden_shape.0;
        let nobserved = hidden_shape.1;
        let nsamples = weights_shape.0;

        let samples_shape = (nsamples, nobserved);

        OrthogonalNMFBlas {
            hidden: hidden,
            weights: weights,

            weights_multiplier: MyMatrix::zeros(weights_shape),
            weights_divisor: MyMatrix::zeros(weights_shape),
            weights_divisor_reconstruction: MyMatrix::zeros(samples_shape),

            hidden_multiplier: MyMatrix::zeros(hidden_shape),
            hidden_divisor: MyMatrix::zeros(hidden_shape),
            hidden_divisor_partial: MyMatrix::zeros((nhidden, nhidden)),

            gamma: OrthogonalNMFBlas::gamma(nhidden),
        }
    }

    /// returns the number of observed variables
    #[inline]
    pub fn nobserved(&self) -> usize {
        self.hidden.shape()[1]
    }

    /// returns the number of hidden variables
    #[inline]
    pub fn nhidden(&self) -> usize {
        self.hidden.shape()[0]
    }

    /// returns the number of data points
    #[inline]
    pub fn nsamples(&self) -> usize {
        self.weights.shape()[0]
    }

    pub fn samples_shape(&self) -> (usize, usize) {
        (self.nsamples(), self.nobserved())
    }

    /// gamma is a symetric matrix with diagonal elements equal to zero
    /// and other elements equal to 1
    pub fn gamma(size: usize) -> MyMatrix {
        let mut gamma = MyMatrix::from_elem((size, size), 1.);
        for x in gamma.diag_mut().iter_mut() {
            *x = 0.
        }
        gamma
    }

    // TODO call these `set` or something similar because
    // opposed to `update_from_multiplier_and_divisor` these
    // don't adjust but change entirely

    /// `samples * hidden.transpose()`
    #[inline]
    pub fn update_weights_multiplier(&mut self, samples: &mut MyMatrix) {
        Gemm::gemm(
            &1.,
            Transpose::NoTrans, &samples.blas(),
            Transpose::Trans, &self.hidden.blas(),
            &0.,
            &mut self.weights_multiplier.blas());

    }

    // TODO this is the slowest
    /// `weights * hidden * hidden.transpose()`
    #[inline]
    pub fn update_weights_divisor(&mut self) {
        // TODO weights * hidden which we compute first is really large
        // we could first compute partial = hidden * hidden.transpose()
        // partial.shape() = (nhidden, nhidden)
        // and then in the second step compute
        // weights * partial.
        // however since we can't alias hidden we need to copy
        // it for this.
        // the question is whether the copying is faster than
        // the larger matrix multiplication. i guess it is.
        // TODO multiplying a matrix by its transpose is symetric
        // can we exploit that ?
        // reconstruction <- weights * hidden
        Gemm::gemm(
            &1.,
            Transpose::NoTrans, &self.weights.blas(),
            Transpose::NoTrans, &self.hidden.blas(),
            &0.,
            &mut self.weights_divisor_reconstruction.blas());
        // divisor <- reconstruction * hidden.transpose()
        Gemm::gemm(
            &1.,
            Transpose::NoTrans, &self.weights_divisor_reconstruction.blas(),
            Transpose::Trans, &self.hidden.blas(),
            &0.,
            &mut self.weights_divisor.blas());
    }

    /// `weights.transpose() * samples`
    #[inline]
    pub fn update_hidden_multiplier(&mut self, samples: &mut MyMatrix) {
        Gemm::gemm(
            &1.,
            Transpose::Trans, &self.weights.blas(),
            Transpose::NoTrans, &samples.blas(),
            &0.,
            &mut self.hidden_multiplier.blas());
    }

    // surprisingly this is the fastest
    /// `weights.transpose() * weights * hidden + alpha * gamma * hidden`
    #[inline]
    pub fn update_hidden_divisor(&mut self, alpha: FloatT) {
        // TODO benchmark whether using clone_from is faster
        let mut weights_copy = self.weights.clone();
        // partial <- weights.transpose() * weights
        Gemm::gemm(
            &1.,
            Transpose::Trans, &self.weights.blas(),
            Transpose::NoTrans, &weights_copy.blas(),
            &0.,
            &mut self.hidden_divisor_partial.blas());
        // partial.shape() = (nhidden, nhidden) very small
        // divisor <- alpha * gamma * hidden
        Gemm::gemm(
            &alpha,
            Transpose::NoTrans, &self.gamma.blas(),
            Transpose::NoTrans, &self.hidden.blas(),
            &0.,
            &mut self.hidden_divisor.blas());
        // divisor <- divisor + partial * hidden
        Gemm::gemm(
            &1.,
            Transpose::NoTrans, &self.hidden_divisor_partial.blas(),
            Transpose::NoTrans, &self.hidden.blas(),
            // add to previous contents of self.hidden_divisor
            &1.,
            &mut self.hidden_divisor.blas());
    }

    /// `result(i,j) <- result(i,j) * multiplier(i,j) / divisor(i,j)`
    #[inline]
    pub fn update_from_multiplier_and_divisor(
        multiplier: &MyMatrix,
        divisor: &MyMatrix,
        result: &mut MyMatrix,
    ) {
        let shape = result.shape_as_tuple();
        assert_eq!(shape, multiplier.shape_as_tuple());
        assert_eq!(shape, divisor.shape_as_tuple());

        for row in 0..shape.0 {
            for col in 0..shape.1 {
                let index = (row, col);
                let mut div = unsafe { divisor.uget(index).clone() };
                // if we have any 0 in any of the matrixes
                // self.weights or self.hidden then
                // divisor will be 0.
                // we can't divide by 0.
                // so we change them to the min positive value.
                if FloatT::zero() == div {
                    div = FloatT::min_positive_value();
                }
                unsafe {
                    *result.uget_mut(index) *= multiplier.uget(index) / div;
                }
            }
        }
    }

    // TODO consider calling this something like iteration_step
    // TODO how many iterations ?
    // TODO compare this to the seoung solution
    /// does one iteration step.
    /// `weights` and `hidden` get better and better with each iteration.
    /// usually around `10000` iterations are required.
    /// `samples` contains one observed per column, one sample per row.
    pub fn iterate(&mut self, alpha: FloatT, samples: &mut MyMatrix) {
        assert_eq!(samples.shape_as_tuple(), self.samples_shape());

        // weights_multiplier <- samples * hidden.transpose()
        self.update_weights_multiplier(samples);
        // weights_divisor <- weights * hidden * hidden.transpose()
        self.update_weights_divisor();
        // hidden_multiplier <- weights.transpose() * samples
        self.update_hidden_multiplier(samples);
        // hidden_divisor <-
        // weights.transpose() * weights * hidden + alpha * gamma * hidden
        self.update_hidden_divisor(alpha);

        // weights(i,j) <-
        // weights(i,j) * weights_multiplier(i,j) / weights_divisor(i,j)
        OrthogonalNMFBlas::update_from_multiplier_and_divisor(
            &self.weights_multiplier,
            &self.weights_divisor,
            &mut self.weights);
        // hidden(i,j) <-
        // hidden(i,j) * hidden_multiplier(i,j) / hidden_divisor(i,j)
        OrthogonalNMFBlas::update_from_multiplier_and_divisor(
            &self.hidden_multiplier,
            &self.hidden_divisor,
            &mut self.hidden);
    }
}
<commit_msg>ortho nmf blas: add assertions that weights and hidden are well formed<commit_after>use std::ops::{Mul, Add};

use rand::{Rand, Rng, Closed01};
use num::{Float, Zero};

use rblas::{Gemm, Matrix};
use rblas::attribute::Transpose;

use ndarray::{ArrayBase, DataOwned, DataMut};
use ndarray::blas::{BlasArrayViewMut, AsBlas};

use helpers::random01;

pub trait ShapeAsTuple<T> {
    fn shape_as_tuple(&self) -> T;
}

pub type FloatT = f32;

impl<T> ShapeAsTuple<(usize, usize)> for ArrayBase<Vec<T>, (usize, usize)> {
    #[inline]
    fn shape_as_tuple(&self) -> (usize, usize) {
        (self.shape()[0], self.shape()[1])
    }
}

pub type Ix = (usize, usize);
pub type MyMatrix = ArrayBase<Vec<FloatT>, Ix>;

pub struct OrthogonalNMFBlas {
    pub hidden: MyMatrix,
    pub weights: MyMatrix,

    // these hold temporary results during an iteration.
    // kept in this struct to prevent unnecessary memory allocations.
    pub weights_multiplier: MyMatrix,
    pub weights_divisor: MyMatrix,
    pub weights_divisor_reconstruction: MyMatrix,

    pub hidden_multiplier: MyMatrix,
    pub hidden_divisor: MyMatrix,
    pub hidden_divisor_partial: MyMatrix,

    pub gamma: MyMatrix,
}

impl OrthogonalNMFBlas
    // where FloatT: 'a + Float + Mul + Zero + Clone + Gemm,
          // ArrayBase<Vec<FloatT>, (usize, usize)>: 'a + AsBlas<FloatT, ArrayBase<Vec<FloatT>, (usize, usize)>, (usize, usize)> + DataOwned<Elem=FloatT> + DataMut<Elem=FloatT>,
          // BlasArrayViewMut<'a, FloatT, (usize, usize)>: Matrix<FloatT>,
          // Closed01<FloatT>: Rand
{
    pub fn new_random01<R: Rng>(nhidden: usize, nobserved: usize, nsamples: usize, rng: &mut R) -> OrthogonalNMFBlas {
        // TODO potentially add some assertions
        let mut hidden = MyMatrix::zeros((nhidden, nobserved));
        for x in hidden.iter_mut() {
            *x = random01(rng);
        }

        let mut weights = MyMatrix::zeros((nsamples, nhidden));
        for x in weights.iter_mut() {
            *x = random01(rng);
        }

        Self::new(hidden, weights)
    }

    pub fn new(hidden: MyMatrix, weights: MyMatrix) -> OrthogonalNMFBlas {
        let hidden_shape = hidden.shape_as_tuple();
        let nhidden = hidden_shape.0;
        let weights_shape = weights.shape_as_tuple();
        assert!(weights_shape.1 == nhidden, "row count of hidden must be equal to column count of weights");

        let nobserved = hidden_shape.1;
        let nsamples = weights_shape.0;

        let samples_shape = (nsamples, nobserved);

        OrthogonalNMFBlas {
            hidden: hidden,
            weights: weights,

            weights_multiplier: MyMatrix::zeros(weights_shape),
            weights_divisor: MyMatrix::zeros(weights_shape),
            weights_divisor_reconstruction: MyMatrix::zeros(samples_shape),

            hidden_multiplier: MyMatrix::zeros(hidden_shape),
            hidden_divisor: MyMatrix::zeros(hidden_shape),
            hidden_divisor_partial: MyMatrix::zeros((nhidden, nhidden)),

            gamma: OrthogonalNMFBlas::gamma(nhidden),
        }
    }

    /// returns the number of observed variables
    #[inline]
    pub fn nobserved(&self) -> usize {
        self.hidden.shape()[1]
    }

    /// returns the number of hidden variables
    #[inline]
    pub fn nhidden(&self) -> usize {
        self.hidden.shape()[0]
    }

    /// returns the number of data points
    #[inline]
    pub fn nsamples(&self) -> usize {
        self.weights.shape()[0]
    }

    pub fn samples_shape(&self) -> (usize, usize) {
        (self.nsamples(), self.nobserved())
    }

    /// gamma is a symetric matrix with diagonal elements equal to zero
    /// and other elements equal to 1
    pub fn gamma(size: usize) -> MyMatrix {
        let mut gamma = MyMatrix::from_elem((size, size), 1.);
        for x in gamma.diag_mut().iter_mut() {
            *x = 0.
        }
        gamma
    }

    // TODO call these `set` or something similar because
    // opposed to `update_from_multiplier_and_divisor` these
    // don't adjust but change entirely

    /// `samples * hidden.transpose()`
    #[inline]
    pub fn update_weights_multiplier(&mut self, samples: &mut MyMatrix) {
        Gemm::gemm(
            &1.,
            Transpose::NoTrans, &samples.blas(),
            Transpose::Trans, &self.hidden.blas(),
            &0.,
            &mut self.weights_multiplier.blas());

    }

    // TODO this is the slowest
    /// `weights * hidden * hidden.transpose()`
    #[inline]
    pub fn update_weights_divisor(&mut self) {
        // TODO weights * hidden which we compute first is really large
        // we could first compute partial = hidden * hidden.transpose()
        // partial.shape() = (nhidden, nhidden)
        // and then in the second step compute
        // weights * partial.
        // however since we can't alias hidden we need to copy
        // it for this.
        // the question is whether the copying is faster than
        // the larger matrix multiplication. i guess it is.
        // TODO multiplying a matrix by its transpose is symetric
        // can we exploit that ?
        // reconstruction <- weights * hidden
        Gemm::gemm(
            &1.,
            Transpose::NoTrans, &self.weights.blas(),
            Transpose::NoTrans, &self.hidden.blas(),
            &0.,
            &mut self.weights_divisor_reconstruction.blas());
        // divisor <- reconstruction * hidden.transpose()
        Gemm::gemm(
            &1.,
            Transpose::NoTrans, &self.weights_divisor_reconstruction.blas(),
            Transpose::Trans, &self.hidden.blas(),
            &0.,
            &mut self.weights_divisor.blas());
    }

    /// `weights.transpose() * samples`
    #[inline]
    pub fn update_hidden_multiplier(&mut self, samples: &mut MyMatrix) {
        Gemm::gemm(
            &1.,
            Transpose::Trans, &self.weights.blas(),
            Transpose::NoTrans, &samples.blas(),
            &0.,
            &mut self.hidden_multiplier.blas());
    }

    // surprisingly this is the fastest
    /// `weights.transpose() * weights * hidden + alpha * gamma * hidden`
    #[inline]
    pub fn update_hidden_divisor(&mut self, alpha: FloatT) {
        // TODO benchmark whether using clone_from is faster
        let mut weights_copy = self.weights.clone();
        // partial <- weights.transpose() * weights
        Gemm::gemm(
            &1.,
            Transpose::Trans, &self.weights.blas(),
            Transpose::NoTrans, &weights_copy.blas(),
            &0.,
            &mut self.hidden_divisor_partial.blas());
        // partial.shape() = (nhidden, nhidden) very small
        // divisor <- alpha * gamma * hidden
        Gemm::gemm(
            &alpha,
            Transpose::NoTrans, &self.gamma.blas(),
            Transpose::NoTrans, &self.hidden.blas(),
            &0.,
            &mut self.hidden_divisor.blas());
        // divisor <- divisor + partial * hidden
        Gemm::gemm(
            &1.,
            Transpose::NoTrans, &self.hidden_divisor_partial.blas(),
            Transpose::NoTrans, &self.hidden.blas(),
            // add to previous contents of self.hidden_divisor
            &1.,
            &mut self.hidden_divisor.blas());
    }

    /// `result(i,j) <- result(i,j) * multiplier(i,j) / divisor(i,j)`
    #[inline]
    pub fn update_from_multiplier_and_divisor(
        multiplier: &MyMatrix,
        divisor: &MyMatrix,
        result: &mut MyMatrix,
    ) {
        let shape = result.shape_as_tuple();
        assert_eq!(shape, multiplier.shape_as_tuple());
        assert_eq!(shape, divisor.shape_as_tuple());

        for row in 0..shape.0 {
            for col in 0..shape.1 {
                let index = (row, col);
                let mut div = unsafe { divisor.uget(index).clone() };
                // if we have any 0 in any of the matrixes
                // self.weights or self.hidden then
                // divisor will be 0.
                // we can't divide by 0.
                // so we change them to the min positive value.
                if FloatT::zero() == div {
                    div = FloatT::min_positive_value();
                }
                unsafe {
                    *result.uget_mut(index) *= multiplier.uget(index) / div;
                }
            }
        }
    }

    // TODO consider calling this something like iteration_step
    // TODO how many iterations ?
    // TODO compare this to the seoung solution
    /// does one iteration step.
    /// `weights` and `hidden` get better and better with each iteration.
    /// usually around `10000` iterations are required.
    /// `samples` contains one observed per column, one sample per row.
    pub fn iterate(&mut self, alpha: FloatT, samples: &mut MyMatrix) {
        assert_eq!(samples.shape_as_tuple(), self.samples_shape());

        // weights_multiplier <- samples * hidden.transpose()
        self.update_weights_multiplier(samples);
        // weights_divisor <- weights * hidden * hidden.transpose()
        self.update_weights_divisor();
        // hidden_multiplier <- weights.transpose() * samples
        self.update_hidden_multiplier(samples);
        // hidden_divisor <-
        // weights.transpose() * weights * hidden + alpha * gamma * hidden
        self.update_hidden_divisor(alpha);

        // weights(i,j) <-
        // weights(i,j) * weights_multiplier(i,j) / weights_divisor(i,j)
        OrthogonalNMFBlas::update_from_multiplier_and_divisor(
            &self.weights_multiplier,
            &self.weights_divisor,
            &mut self.weights);
        // hidden(i,j) <-
        // hidden(i,j) * hidden_multiplier(i,j) / hidden_divisor(i,j)
        OrthogonalNMFBlas::update_from_multiplier_and_divisor(
            &self.hidden_multiplier,
            &self.hidden_divisor,
            &mut self.hidden);
    }
}
<|endoftext|>


<commit_before><commit_msg>Improve readability<commit_after><|endoftext|>


<commit_before><commit_msg>Simplify.<commit_after><|endoftext|>


<commit_before><commit_msg>removed irrelevant comment<commit_after><|endoftext|>


<commit_before>//! The CXX code generator for constructing and compiling C++ code.
//!
//! This is intended to be embedded into higher-level code generators.

mod gen;
mod syntax;

pub use crate::gen::Opt;
use proc_macro2::TokenStream;

pub use crate::gen::{Error, Result};

/// Results of code generation.
pub struct GeneratedCode {
    /// The bytes of a C++ header file.
    pub header: Vec<u8>,
    /// The bytes of a C++ implementation file (e.g. .cc, cpp etc.)
    pub cxx: Vec<u8>,
}

/// Generate C++ bindings code from a Rust token stream. This should be a Rust
/// token stream which somewhere contains a `#[cxx::bridge] mod {}`.
pub fn generate_header_and_cc(rust_source: TokenStream, opt: Opt) -> Result<GeneratedCode> {
    let syntax = syn::parse2(rust_source)?;
    match gen::generate(syntax, opt, true, true) {
        Ok((Some(header), Some(cxx))) => Ok(GeneratedCode { header, cxx }),
        Err(err) => Err(err),
        _ => panic!("Unexpected generation"),
    }
}

#[cfg(test)]
mod test {
    use quote::quote;

    #[test]
    fn test_positive() {
        let rs = quote! {
            #[cxx::bridge]
            mod ffi {
                extern "C" {
                    fn in_C();
                }
                extern "Rust" {
                    fn in_rs();
                }
            }
        };
        let code = crate::generate_header_and_cc(rs).unwrap();
        assert!(code.cxx.len() > 0);
        assert!(code.header.len() > 0);
    }

    #[test]
    fn test_negative() {
        let rs = quote! {};
        assert!(crate::generate_header_and_cc(rs).is_err())
    }
}
<commit_msg>Fix compilation of cxx-gen unit test<commit_after>//! The CXX code generator for constructing and compiling C++ code.
//!
//! This is intended to be embedded into higher-level code generators.

mod gen;
mod syntax;

pub use crate::gen::Opt;
use proc_macro2::TokenStream;

pub use crate::gen::{Error, Result};

/// Results of code generation.
pub struct GeneratedCode {
    /// The bytes of a C++ header file.
    pub header: Vec<u8>,
    /// The bytes of a C++ implementation file (e.g. .cc, cpp etc.)
    pub cxx: Vec<u8>,
}

/// Generate C++ bindings code from a Rust token stream. This should be a Rust
/// token stream which somewhere contains a `#[cxx::bridge] mod {}`.
pub fn generate_header_and_cc(rust_source: TokenStream, opt: Opt) -> Result<GeneratedCode> {
    let syntax = syn::parse2(rust_source)?;
    match gen::generate(syntax, opt, true, true) {
        Ok((Some(header), Some(cxx))) => Ok(GeneratedCode { header, cxx }),
        Err(err) => Err(err),
        _ => panic!("Unexpected generation"),
    }
}

#[cfg(test)]
mod test {
    use crate::Opt;
    use quote::quote;

    #[test]
    fn test_positive() {
        let rs = quote! {
            #[cxx::bridge]
            mod ffi {
                extern "C" {
                    fn in_C();
                }
                extern "Rust" {
                    fn in_rs();
                }
            }
        };
        let opt = Opt::default();
        let code = crate::generate_header_and_cc(rs, opt).unwrap();
        assert!(code.cxx.len() > 0);
        assert!(code.header.len() > 0);
    }

    #[test]
    fn test_negative() {
        let rs = quote! {};
        let opt = Opt::default();
        assert!(crate::generate_header_and_cc(rs, opt).is_err())
    }
}
<|endoftext|>


<commit_before>//! Seat global utilities
//!
//! This module provides you with utilities for handling the seat globals
//! and the associated input wayland objects.
//!
//! ## How to use it
//!
//! ### Initialization
//!
//! ```
//! # extern crate wayland_server;
//! # #[macro_use] extern crate smithay;
//!
//! use smithay::wayland::seat::Seat;
//!
//! # fn main(){
//! # let (_display, mut event_loop) = wayland_server::create_display();
//! // insert the seat:
//! let (seat_state_token, seat_global) = Seat::new(
//!     &mut event_loop,
//!     "seat-0".into(), // the name of the seat, will be advertize to clients
//!     None /* insert a logger here*/
//! );
//! # }
//! ```
//!
//! ### Run usage
//!
//! Once the seat is initialized, you can add capabilities to it.
//!
//! Currently, only pointer and keyboard capabilities are supported by
//! smithay.
//!
//! You can add these capabilities via methods of the `Seat` struct that was
//! inserted in the event loop, that you can retreive via its token:
//!
//! ```
//! # extern crate wayland_server;
//! # #[macro_use] extern crate smithay;
//! #
//! # use smithay::wayland::seat::Seat;
//! #
//! # fn main(){
//! # let (_display, mut event_loop) = wayland_server::create_display();
//! # let (seat_state_token, seat_global) = Seat::new(
//! #     &mut event_loop,
//! #     "seat-0".into(), // the name of the seat, will be advertize to clients
//! #     None /* insert a logger here*/
//! # );
//! let pointer_handle = event_loop.state().get_mut(&seat_state_token).add_pointer();
//! # }
//! ```
//!
//! These handles can be cloned and sent accross thread, so you can keep one around
//! in your event-handling code to forward inputs to your clients.

mod keyboard;
mod pointer;

pub use self::keyboard::{Error as KeyboardError, KeyboardHandle};
pub use self::pointer::PointerHandle;
use wayland_server::{Client, EventLoop, EventLoopHandle, Global, Liveness, Resource, StateToken};
use wayland_server::protocol::{wl_keyboard, wl_pointer, wl_seat};

/// Internal data of a seat global
///
/// This struct gives you access to the control of the
/// capabilities of the associated seat.
///
/// It is directly inserted in the event loop by its `new` method.
///
/// See module-level documentation for details of use.
pub struct Seat {
    log: ::slog::Logger,
    name: String,
    pointer: Option<PointerHandle>,
    keyboard: Option<KeyboardHandle>,
    known_seats: Vec<wl_seat::WlSeat>,
}

impl Seat {
    /// Create a new seat global
    ///
    /// A new seat global is created with given name and inserted
    /// into this event loop.
    ///
    /// You are provided with the state token to retrieve it (allowing
    /// you to add or remove capabilities from it), and the global handle,
    /// in case you want to remove it.
    pub fn new<L>(
        evl: &mut EventLoop, name: String, logger: L
    ) -> (StateToken<Seat>, Global<wl_seat::WlSeat, StateToken<Seat>>)
    where
        L: Into<Option<::slog::Logger>>,
    {
        let log = ::slog_or_stdlog(logger);
        let seat = Seat {
            log: log.new(o!("smithay_module" => "seat_handler", "seat_name" => name.clone())),
            name: name,
            pointer: None,
            keyboard: None,
            known_seats: Vec::new(),
        };
        let token = evl.state().insert(seat);
        // TODO: support version 5 (axis)
        let global = evl.register_global(4, seat_global_bind, token.clone());
        (token, global)
    }

    /// Adds the pointer capability to this seat
    ///
    /// You are provided a `PointerHandle`, which allows you to send input events
    /// to this keyboard. This handle can be cloned and sent accross threads.
    ///
    /// Calling this method on a seat that already has a pointer capability
    /// will overwrite it, and will be seen by the clients as if the
    /// mouse was unplugged and a new one was plugged.
    pub fn add_pointer(&mut self) -> PointerHandle {
        let pointer = self::pointer::create_pointer_handler();
        if self.pointer.is_some() {
            // there is already a pointer, remove it and notify the clients
            // of the change
            self.pointer = None;
            let caps = self.compute_caps();
            for seat in &self.known_seats {
                seat.capabilities(caps);
            }
        }
        self.pointer = Some(pointer.clone());
        let caps = self.compute_caps();
        for seat in &self.known_seats {
            seat.capabilities(caps);
        }
        pointer
    }

    /// Remove the pointer capability from this seat
    ///
    /// Clients will be appropriately notified.
    pub fn remove_pointer(&mut self) {
        if self.pointer.is_some() {
            self.pointer = None;
            let caps = self.compute_caps();
            for seat in &self.known_seats {
                seat.capabilities(caps);
            }
        }
    }

    /// Adds the keyboard capability to this seat
    ///
    /// You are provided a `KbdHandle`, which allows you to send input events
    /// to this keyboard. This handle can be cloned and sent accross threads.
    ///
    /// You also provide a Model/Layout/Variant/Options specification of the
    /// keymap to be used for this keyboard, as well as any repeat-info that
    /// will be forwarded to the clients.
    ///
    /// Calling this method on a seat that already has a keyboard capability
    /// will overwrite it, and will be seen by the clients as if the
    /// keyboard was unplugged and a new one was plugged.
    pub fn add_keyboard(
        &mut self, model: &str, layout: &str, variant: &str, options: Option<String>, repeat_delay: i32,
        repeat_rate: i32,
    ) -> Result<KeyboardHandle, KeyboardError> {
        let keyboard = self::keyboard::create_keyboard_handler(
            "evdev", // we need this one
            model,
            layout,
            variant,
            options,
            repeat_delay,
            repeat_rate,
            &self.log,
        )?;
        if self.keyboard.is_some() {
            // there is already a keyboard, remove it and notify the clients
            // of the change
            self.keyboard = None;
            let caps = self.compute_caps();
            for seat in &self.known_seats {
                seat.capabilities(caps);
            }
        }
        self.keyboard = Some(keyboard.clone());
        let caps = self.compute_caps();
        for seat in &self.known_seats {
            seat.capabilities(caps);
        }
        Ok(keyboard)
    }

    /// Remove the keyboard capability from this seat
    ///
    /// Clients will be appropriately notified.
    pub fn remove_keyboard(&mut self) {
        if self.keyboard.is_some() {
            self.keyboard = None;
            let caps = self.compute_caps();
            for seat in &self.known_seats {
                seat.capabilities(caps);
            }
        }
    }

    /// Cleanup internal states from old resources
    ///
    /// Deletes all remnnant of ressources from clients that
    /// are now disconnected.
    ///
    /// It can be wise to run this from time to time.
    pub fn cleanup(&mut self) {
        if let Some(ref pointer) = self.pointer {
            pointer.cleanup_old_pointers();
        }
        if let Some(ref kbd) = self.keyboard {
            kbd.cleanup_old_kbds();
        }
        self.known_seats.retain(|s| s.status() == Liveness::Alive);
    }

    fn compute_caps(&self) -> wl_seat::Capability {
        let mut caps = wl_seat::Capability::empty();
        if self.pointer.is_some() {
            caps |= wl_seat::Capability::Pointer;
        }
        if self.keyboard.is_some() {
            caps |= wl_seat::Capability::Keyboard;
        }
        caps
    }
}

fn seat_global_bind(
    evlh: &mut EventLoopHandle, token: &mut StateToken<Seat>, _: &Client, seat: wl_seat::WlSeat
) {
    evlh.register(&seat, seat_implementation(), token.clone(), None);
    let seat_mgr = evlh.state().get_mut(token);
    seat.name(seat_mgr.name.clone());
    seat.capabilities(seat_mgr.compute_caps());
    seat_mgr.known_seats.push(seat);
}

fn seat_implementation() -> wl_seat::Implementation<StateToken<Seat>> {
    wl_seat::Implementation {
        get_pointer: |evlh, token, _, _, pointer| {
            evlh.register(&pointer, pointer_implementation(), (), None);
            if let Some(ref ptr_handle) = evlh.state().get(token).pointer {
                ptr_handle.new_pointer(pointer);
            } else {
                // we should send a protocol error... but the protocol does not allow
                // us, so this pointer will just remain inactive ¯\_(ツ)_/¯
            }
        },
        get_keyboard: |evlh, token, _, _, keyboard| {
            evlh.register(&keyboard, keyboard_implementation(), (), None);
            if let Some(ref kbd_handle) = evlh.state().get(token).keyboard {
                kbd_handle.new_kbd(keyboard);
            } else {
                // same, should error but cant
            }
        },
        get_touch: |_evlh, _token, _, _, _touch| {
            // TODO
        },
        release: |_, _, _, _| {},
    }
}

fn pointer_implementation() -> wl_pointer::Implementation<()> {
    wl_pointer::Implementation {
        set_cursor: |_, _, _, _, _, _, _, _| {},
        release: |_, _, _, _| {},
    }
}

fn keyboard_implementation() -> wl_keyboard::Implementation<()> {
    wl_keyboard::Implementation {
        release: |_, _, _, _| {},
    }
}
<commit_msg>Fix seats of version 1<commit_after>//! Seat global utilities
//!
//! This module provides you with utilities for handling the seat globals
//! and the associated input wayland objects.
//!
//! ## How to use it
//!
//! ### Initialization
//!
//! ```
//! # extern crate wayland_server;
//! # #[macro_use] extern crate smithay;
//!
//! use smithay::wayland::seat::Seat;
//!
//! # fn main(){
//! # let (_display, mut event_loop) = wayland_server::create_display();
//! // insert the seat:
//! let (seat_state_token, seat_global) = Seat::new(
//!     &mut event_loop,
//!     "seat-0".into(), // the name of the seat, will be advertize to clients
//!     None /* insert a logger here*/
//! );
//! # }
//! ```
//!
//! ### Run usage
//!
//! Once the seat is initialized, you can add capabilities to it.
//!
//! Currently, only pointer and keyboard capabilities are supported by
//! smithay.
//!
//! You can add these capabilities via methods of the `Seat` struct that was
//! inserted in the event loop, that you can retreive via its token:
//!
//! ```
//! # extern crate wayland_server;
//! # #[macro_use] extern crate smithay;
//! #
//! # use smithay::wayland::seat::Seat;
//! #
//! # fn main(){
//! # let (_display, mut event_loop) = wayland_server::create_display();
//! # let (seat_state_token, seat_global) = Seat::new(
//! #     &mut event_loop,
//! #     "seat-0".into(), // the name of the seat, will be advertize to clients
//! #     None /* insert a logger here*/
//! # );
//! let pointer_handle = event_loop.state().get_mut(&seat_state_token).add_pointer();
//! # }
//! ```
//!
//! These handles can be cloned and sent accross thread, so you can keep one around
//! in your event-handling code to forward inputs to your clients.

mod keyboard;
mod pointer;

pub use self::keyboard::{Error as KeyboardError, KeyboardHandle};
pub use self::pointer::PointerHandle;
use wayland_server::{Client, EventLoop, EventLoopHandle, Global, Liveness, Resource, StateToken};
use wayland_server::protocol::{wl_keyboard, wl_pointer, wl_seat};

/// Internal data of a seat global
///
/// This struct gives you access to the control of the
/// capabilities of the associated seat.
///
/// It is directly inserted in the event loop by its `new` method.
///
/// See module-level documentation for details of use.
pub struct Seat {
    log: ::slog::Logger,
    name: String,
    pointer: Option<PointerHandle>,
    keyboard: Option<KeyboardHandle>,
    known_seats: Vec<wl_seat::WlSeat>,
}

impl Seat {
    /// Create a new seat global
    ///
    /// A new seat global is created with given name and inserted
    /// into this event loop.
    ///
    /// You are provided with the state token to retrieve it (allowing
    /// you to add or remove capabilities from it), and the global handle,
    /// in case you want to remove it.
    pub fn new<L>(
        evl: &mut EventLoop, name: String, logger: L
    ) -> (StateToken<Seat>, Global<wl_seat::WlSeat, StateToken<Seat>>)
    where
        L: Into<Option<::slog::Logger>>,
    {
        let log = ::slog_or_stdlog(logger);
        let seat = Seat {
            log: log.new(o!("smithay_module" => "seat_handler", "seat_name" => name.clone())),
            name: name,
            pointer: None,
            keyboard: None,
            known_seats: Vec::new(),
        };
        let token = evl.state().insert(seat);
        // TODO: support version 5 (axis)
        let global = evl.register_global(4, seat_global_bind, token.clone());
        (token, global)
    }

    /// Adds the pointer capability to this seat
    ///
    /// You are provided a `PointerHandle`, which allows you to send input events
    /// to this keyboard. This handle can be cloned and sent accross threads.
    ///
    /// Calling this method on a seat that already has a pointer capability
    /// will overwrite it, and will be seen by the clients as if the
    /// mouse was unplugged and a new one was plugged.
    pub fn add_pointer(&mut self) -> PointerHandle {
        let pointer = self::pointer::create_pointer_handler();
        if self.pointer.is_some() {
            // there is already a pointer, remove it and notify the clients
            // of the change
            self.pointer = None;
            let caps = self.compute_caps();
            for seat in &self.known_seats {
                seat.capabilities(caps);
            }
        }
        self.pointer = Some(pointer.clone());
        let caps = self.compute_caps();
        for seat in &self.known_seats {
            seat.capabilities(caps);
        }
        pointer
    }

    /// Remove the pointer capability from this seat
    ///
    /// Clients will be appropriately notified.
    pub fn remove_pointer(&mut self) {
        if self.pointer.is_some() {
            self.pointer = None;
            let caps = self.compute_caps();
            for seat in &self.known_seats {
                seat.capabilities(caps);
            }
        }
    }

    /// Adds the keyboard capability to this seat
    ///
    /// You are provided a `KbdHandle`, which allows you to send input events
    /// to this keyboard. This handle can be cloned and sent accross threads.
    ///
    /// You also provide a Model/Layout/Variant/Options specification of the
    /// keymap to be used for this keyboard, as well as any repeat-info that
    /// will be forwarded to the clients.
    ///
    /// Calling this method on a seat that already has a keyboard capability
    /// will overwrite it, and will be seen by the clients as if the
    /// keyboard was unplugged and a new one was plugged.
    pub fn add_keyboard(
        &mut self, model: &str, layout: &str, variant: &str, options: Option<String>, repeat_delay: i32,
        repeat_rate: i32,
    ) -> Result<KeyboardHandle, KeyboardError> {
        let keyboard = self::keyboard::create_keyboard_handler(
            "evdev", // we need this one
            model,
            layout,
            variant,
            options,
            repeat_delay,
            repeat_rate,
            &self.log,
        )?;
        if self.keyboard.is_some() {
            // there is already a keyboard, remove it and notify the clients
            // of the change
            self.keyboard = None;
            let caps = self.compute_caps();
            for seat in &self.known_seats {
                seat.capabilities(caps);
            }
        }
        self.keyboard = Some(keyboard.clone());
        let caps = self.compute_caps();
        for seat in &self.known_seats {
            seat.capabilities(caps);
        }
        Ok(keyboard)
    }

    /// Remove the keyboard capability from this seat
    ///
    /// Clients will be appropriately notified.
    pub fn remove_keyboard(&mut self) {
        if self.keyboard.is_some() {
            self.keyboard = None;
            let caps = self.compute_caps();
            for seat in &self.known_seats {
                seat.capabilities(caps);
            }
        }
    }

    /// Cleanup internal states from old resources
    ///
    /// Deletes all remnnant of ressources from clients that
    /// are now disconnected.
    ///
    /// It can be wise to run this from time to time.
    pub fn cleanup(&mut self) {
        if let Some(ref pointer) = self.pointer {
            pointer.cleanup_old_pointers();
        }
        if let Some(ref kbd) = self.keyboard {
            kbd.cleanup_old_kbds();
        }
        self.known_seats.retain(|s| s.status() == Liveness::Alive);
    }

    fn compute_caps(&self) -> wl_seat::Capability {
        let mut caps = wl_seat::Capability::empty();
        if self.pointer.is_some() {
            caps |= wl_seat::Capability::Pointer;
        }
        if self.keyboard.is_some() {
            caps |= wl_seat::Capability::Keyboard;
        }
        caps
    }
}

fn seat_global_bind(
    evlh: &mut EventLoopHandle, token: &mut StateToken<Seat>, _: &Client, seat: wl_seat::WlSeat
) {
    evlh.register(&seat, seat_implementation(), token.clone(), None);
    let seat_mgr = evlh.state().get_mut(token);
    if seat.version() >= 2 {
        seat.name(seat_mgr.name.clone());
    }
    seat.capabilities(seat_mgr.compute_caps());
    seat_mgr.known_seats.push(seat);
}

fn seat_implementation() -> wl_seat::Implementation<StateToken<Seat>> {
    wl_seat::Implementation {
        get_pointer: |evlh, token, _, _, pointer| {
            evlh.register(&pointer, pointer_implementation(), (), None);
            if let Some(ref ptr_handle) = evlh.state().get(token).pointer {
                ptr_handle.new_pointer(pointer);
            } else {
                // we should send a protocol error... but the protocol does not allow
                // us, so this pointer will just remain inactive ¯\_(ツ)_/¯
            }
        },
        get_keyboard: |evlh, token, _, _, keyboard| {
            evlh.register(&keyboard, keyboard_implementation(), (), None);
            if let Some(ref kbd_handle) = evlh.state().get(token).keyboard {
                kbd_handle.new_kbd(keyboard);
            } else {
                // same, should error but cant
            }
        },
        get_touch: |_evlh, _token, _, _, _touch| {
            // TODO
        },
        release: |_, _, _, _| {},
    }
}

fn pointer_implementation() -> wl_pointer::Implementation<()> {
    wl_pointer::Implementation {
        set_cursor: |_, _, _, _, _, _, _, _| {},
        release: |_, _, _, _| {},
    }
}

fn keyboard_implementation() -> wl_keyboard::Implementation<()> {
    wl_keyboard::Implementation {
        release: |_, _, _, _| {},
    }
}
<|endoftext|>


<commit_before>//! Receive incoming Iridium messages through their Direct IP service.
//!
//! Iridium DirectIP is a service provided by the Iridium company. New Mobile
//! Originated messages are forwarded from the Iridium servers to a configured
//! IP address. The Iridum service attempts to initate a TCP connection to port
//! 10800 at the specified IP. IF the connection is successful, the MO message
//! is transmitted, then the connection is closed.
//!
//! This module provides a `Server` structure, which can be created to run
//! forever and receive those incoming MO messages.

use std::io;
use std::net::{TcpListener, TcpStream, ToSocketAddrs};
use std::path::Path;
use std::sync::Arc;
use std::thread;

use super::filesystem::Storage;
use super::message::Message;

/// A Iridium DirectIP server.
///
/// The server will listen on a socket address for incoming Iridium SBD Mobile Originated
/// messages. Incoming messages will be stored using `sbd::filesystem::Storage`. Errors are logged
/// using the logging framework.
pub struct Server<A: ToSocketAddrs + Sync> {
    addr: A,
    listener: Option<TcpListener>,
    storage: Arc<Storage>,
}

impl<A: ToSocketAddrs + Sync> Server<A> {
    /// Creates a new server that will listen on `addr` and write messages to `root`.
    ///
    /// This method does not actually bind to the socket address or do anything with the root
    /// directory. Use `bind` and `serve_forever` to actually do stuff.
    ///
    /// The `root` parameters is used to create a new `sbd::filesystem::Storage`, and the server
    /// will store all incoming messages under `root`.
    ///
    /// # Examples
    ///
    /// ```
    /// let server = sbd::directip::Server::new("0.0.0.0:10800", "/var/iridium");
    /// ```
    pub fn new<P: AsRef<Path>>(addr: A, root: P) -> Server<A> {
        Server {
            addr: addr,
            listener: None,
            storage: Arc::new(Storage::new(root)),
        }
    }

    /// Binds this server to its tcp socket.
    ///
    /// This is a seperate operation from `serve_forever` so that we can capture any errors
    /// associated with the underlying `TcpListener::bind`.
    ///
    /// # Examples
    ///
    /// ```
    /// let mut server = sbd::directip::Server::new("0.0.0.0:10800", "/var/iridium");
    /// server.bind().unwrap();
    /// ```
    pub fn bind(&mut self) -> io::Result<()> {
        self.listener = Some(try!(self.create_listener()));
        Ok(())
    }

    /// Starts the DirectIP server and serves forever.
    ///
    /// # Panics
    ///
    /// This method panics if it has a problem binding to the tcp socket address. To avoid a panic,
    /// use `Server::bind` before calling `Server::serve_forever`.
    ///
    /// # Examples
    ///
    /// ```no_run
    /// let mut server = sbd::directip::Server::new("0.0.0.0:10800", "/var/iridium");
    /// server.bind().unwrap();
    /// server.serve_forever();
    /// ```
    pub fn serve_forever(&mut self) {
        let listener = match self.listener {
            Some(ref listener) => listener,
            None => {
                self.listener = Some(self.create_listener().unwrap());
                self.listener.as_ref().unwrap()
            }
        };
        for stream in listener.incoming() {
            match stream {
                Ok(stream) => {
                    let storage = self.storage.clone();
                    thread::spawn(move || handle_stream(stream, storage));
                }
                Err(err) => {
                    thread::spawn(move || handle_error(err));
                }
            }
        }
    }

    fn create_listener(&self) -> io::Result<TcpListener> {
        TcpListener::bind(&self.addr)
    }
}

/// Handles an incoming DirectIP stream.
fn handle_stream(stream: TcpStream, storage: Arc<Storage>) {
    match stream.peer_addr() {
        Ok(addr) => {
            debug!("Handling TcpStream from {}", addr);
        }
        Err(err) => {
            warn!("Problem when extracting peer address from TcpStream, but we'll press on: {:?}",
                  err);
        }
    }
    let ref message = match Message::read_from(stream) {
        Ok(message) => {
            info!("Recieved message with {} byte payload",
                  message.payload_ref().len());
            message
        }
        Err(err) => {
            error!("Error when reading message: {:?}", err);
            return;
        }
    };
    match storage.store(message) {
        Ok(path) => info!("Stored message to {:?}", path),
        Err(err) => error!("Problem storing message: {:?}", err),
    }
}

/// Handles an error when handling a connection.
fn handle_error(err: io::Error) {
    error!("Error when receiving tcp communication: {:?}", err);
}
<commit_msg>Derive debug for Server<commit_after>//! Receive incoming Iridium messages through their Direct IP service.
//!
//! Iridium DirectIP is a service provided by the Iridium company. New Mobile
//! Originated messages are forwarded from the Iridium servers to a configured
//! IP address. The Iridum service attempts to initate a TCP connection to port
//! 10800 at the specified IP. IF the connection is successful, the MO message
//! is transmitted, then the connection is closed.
//!
//! This module provides a `Server` structure, which can be created to run
//! forever and receive those incoming MO messages.

use std::io;
use std::net::{TcpListener, TcpStream, ToSocketAddrs};
use std::path::Path;
use std::sync::Arc;
use std::thread;

use super::filesystem::Storage;
use super::message::Message;

/// A Iridium DirectIP server.
///
/// The server will listen on a socket address for incoming Iridium SBD Mobile Originated
/// messages. Incoming messages will be stored using `sbd::filesystem::Storage`. Errors are logged
/// using the logging framework.
#[allow(missing_copy_implementations)]
#[derive(Debug)]
pub struct Server<A: ToSocketAddrs + Sync> {
    addr: A,
    listener: Option<TcpListener>,
    storage: Arc<Storage>,
}

impl<A: ToSocketAddrs + Sync> Server<A> {
    /// Creates a new server that will listen on `addr` and write messages to `root`.
    ///
    /// This method does not actually bind to the socket address or do anything with the root
    /// directory. Use `bind` and `serve_forever` to actually do stuff.
    ///
    /// The `root` parameters is used to create a new `sbd::filesystem::Storage`, and the server
    /// will store all incoming messages under `root`.
    ///
    /// # Examples
    ///
    /// ```
    /// let server = sbd::directip::Server::new("0.0.0.0:10800", "/var/iridium");
    /// ```
    pub fn new<P: AsRef<Path>>(addr: A, root: P) -> Server<A> {
        Server {
            addr: addr,
            listener: None,
            storage: Arc::new(Storage::new(root)),
        }
    }

    /// Binds this server to its tcp socket.
    ///
    /// This is a seperate operation from `serve_forever` so that we can capture any errors
    /// associated with the underlying `TcpListener::bind`.
    ///
    /// # Examples
    ///
    /// ```
    /// let mut server = sbd::directip::Server::new("0.0.0.0:10800", "/var/iridium");
    /// server.bind().unwrap();
    /// ```
    pub fn bind(&mut self) -> io::Result<()> {
        self.listener = Some(try!(self.create_listener()));
        Ok(())
    }

    /// Starts the DirectIP server and serves forever.
    ///
    /// # Panics
    ///
    /// This method panics if it has a problem binding to the tcp socket address. To avoid a panic,
    /// use `Server::bind` before calling `Server::serve_forever`.
    ///
    /// # Examples
    ///
    /// ```no_run
    /// let mut server = sbd::directip::Server::new("0.0.0.0:10800", "/var/iridium");
    /// server.bind().unwrap();
    /// server.serve_forever();
    /// ```
    pub fn serve_forever(&mut self) {
        let listener = match self.listener {
            Some(ref listener) => listener,
            None => {
                self.listener = Some(self.create_listener().unwrap());
                self.listener.as_ref().unwrap()
            }
        };
        for stream in listener.incoming() {
            match stream {
                Ok(stream) => {
                    let storage = self.storage.clone();
                    thread::spawn(move || handle_stream(stream, storage));
                }
                Err(err) => {
                    thread::spawn(move || handle_error(err));
                }
            }
        }
    }

    fn create_listener(&self) -> io::Result<TcpListener> {
        TcpListener::bind(&self.addr)
    }
}

/// Handles an incoming DirectIP stream.
fn handle_stream(stream: TcpStream, storage: Arc<Storage>) {
    match stream.peer_addr() {
        Ok(addr) => {
            debug!("Handling TcpStream from {}", addr);
        }
        Err(err) => {
            warn!("Problem when extracting peer address from TcpStream, but we'll press on: {:?}",
                  err);
        }
    }
    let ref message = match Message::read_from(stream) {
        Ok(message) => {
            info!("Recieved message with {} byte payload",
                  message.payload_ref().len());
            message
        }
        Err(err) => {
            error!("Error when reading message: {:?}", err);
            return;
        }
    };
    match storage.store(message) {
        Ok(path) => info!("Stored message to {:?}", path),
        Err(err) => error!("Problem storing message: {:?}", err),
    }
}

/// Handles an error when handling a connection.
fn handle_error(err: io::Error) {
    error!("Error when receiving tcp communication: {:?}", err);
}
<|endoftext|>


<commit_before>use std::io;
use std::io::prelude::*;

type SudokuCandidate = u64;
const SUDOKU_DIGIT_BASE: u32 = 10;
const SUDOKU_CANDIDATE_SIZE: usize = 9;
const SUDOKU_BOX_SIZE: usize = 3;
const SUDOKU_GROUP_SIZE: usize = 9;
const SUDOKU_CELL_SIZE: usize = 81;
const SUDOKU_ALL_CANDIDATES: SudokuCandidate = ((1 << SUDOKU_CANDIDATE_SIZE) - 1);

// Sudoku cell that contains candidates as a bitboard
#[derive(Clone, Copy)]
struct SudokuCell {
    candidates: SudokuCandidate
}

impl SudokuCell {
    fn new() -> SudokuCell {
        SudokuCell { candidates: SUDOKU_ALL_CANDIDATES }
    }

    fn to_string(&self) -> String {
        let mut line = String::new();
        for candidate in 0..(SUDOKU_CANDIDATE_SIZE as SudokuCandidate) {
            if self.has_candidate(&candidate) {
                line.push_str(&(candidate+1).to_string());
            }
        }
        line
    }

    // Input '1'..'9'
    fn preset_candidate(&mut self, ch: char) {
        let code_digit_base = '1'.to_digit(SUDOKU_DIGIT_BASE).unwrap();
        match ch {
            '1'...'9' => {
                let number = (ch.to_digit(SUDOKU_DIGIT_BASE).unwrap() - code_digit_base) as SudokuCandidate;
                self.candidates = self.digit_to_candidate(&number);
            }
            _ => {}
        }
    }

    fn clear_candidate(&mut self) {
        self.candidates = 0;
    }

    // Input 0..8
    fn overwrite_candidate(&mut self, candidate: SudokuCandidate) {
        if self.count_candidates() > 1 {
            self.candidates = self.digit_to_candidate(&candidate);
        }
    }

    fn count_candidates(&self) -> usize {
        let f = |candidate| {
            if (self.candidates & self.digit_to_candidate(&candidate))
                != 0 { 1 } else { 0 } };
        (0..SUDOKU_CANDIDATE_SIZE as SudokuCandidate).fold(
            0, |sum, candidates| sum + f(candidates))
    }

    fn has_unique_candidate(&self) -> bool {
        // Check whether only one bit is set
        (self.candidates & (self.candidates - 1)) == 0
    }

    fn has_all_candidates(&self) -> bool {
        self.candidates == SUDOKU_ALL_CANDIDATES
    }

    // Input 0..8
    fn can_mask(&mut self, candidates: SudokuCandidate) -> bool {
        (self.candidates & self.digit_to_candidate(&candidates)) != 0
    }

    fn mask_candidate(&mut self, rhs: &SudokuCell) {
        if rhs.count_candidates() == 1 {
            self.candidates &= !rhs.candidates;
        }
    }

    fn merge_candidate(&mut self, rhs: &SudokuCell) {
        self.candidates |= rhs.candidates;
    }

    // Returns whether no candidates are merged
    fn merge_unique_candidate(&mut self, rhs: &SudokuCell) -> bool {
        if rhs.has_unique_candidate() {
            if (self.candidates & rhs.candidates) != 0 {
                return true;
            }
            self.candidates |= rhs.candidates;
        }
        false
    }

    // Inner methods
    // Input 0..8
    fn digit_to_candidate(&self, candidate: &SudokuCandidate) -> SudokuCandidate {
        (1 as SudokuCandidate) << candidate
    }

    // Input 0..8
    fn has_candidate(&self, candidate: &SudokuCandidate) -> bool {
        (self.candidates & self.digit_to_candidate(&candidate)) != 0
    }
}

// Generator for sudoku cellgroups
struct SudokuGroupGen {
    index: usize
}

impl SudokuGroupGen {
    fn new() -> SudokuGroupGen {
        SudokuGroupGen { index:0 }
    }

    fn next(&mut self) -> Option<Vec<usize>> {
        if self.index < SUDOKU_GROUP_SIZE {
            let lower = self.index * SUDOKU_GROUP_SIZE;
            let upper = (self.index + 1) * SUDOKU_GROUP_SIZE;
            self.index += 1;
            Some((lower..upper).collect::<Vec<_>>())
        } else if self.index < (SUDOKU_GROUP_SIZE * 2) {
            let column = self.index - SUDOKU_GROUP_SIZE;
            self.index += 1;
            Some((0..SUDOKU_GROUP_SIZE).map(|i| column + i * SUDOKU_GROUP_SIZE).collect::<Vec<_>>())
        } else if self.index < (SUDOKU_GROUP_SIZE * 3) {
            let box_index = self.index - SUDOKU_GROUP_SIZE * 2;
            let offset = (box_index % 3) * 3  + (box_index / 3) * SUDOKU_GROUP_SIZE * 3;
            let mut indexes : Vec<usize> = Vec::new();
            for row in 0..SUDOKU_BOX_SIZE {
                let x = (0..SUDOKU_BOX_SIZE).map(|column| row * SUDOKU_GROUP_SIZE + column + offset).collect::<Vec<_>>();
                indexes.extend(x);
            }
            self.index += 1;
            Some(indexes)
        } else {
            None
        }
    }
}

// Sudoku cell map
struct SudokuMap {
    cells : Vec<SudokuCell>
}

impl SudokuMap {
    fn new(line: &str) -> SudokuMap {
        let mut cells = vec![SudokuCell::new(); SUDOKU_CELL_SIZE];
        for (index, ch) in line.chars().enumerate() {
            cells[index].preset_candidate(ch);
        }
        SudokuMap { cells:cells }
    }

    fn to_string(&self) -> String {
        let mut full_text = String::new();

        for row in 0..SUDOKU_GROUP_SIZE {
            let mut line = String::new();
            for column in 0..SUDOKU_GROUP_SIZE {
                let index = row * SUDOKU_GROUP_SIZE + column;
                let cell_str = self.cells[index].to_string();
                line.push_str(&cell_str);
                line.push_str(":");
            }
            line.push_str("\n");
            full_text.push_str(&line);
        }
        full_text
    }

    fn solve(&mut self) -> bool {
        self.solve_from(0)
    }

    fn solve_from(&mut self, start_pos : usize) -> bool {
        self.filter_unique_candidates();
        if !self.is_consistent() {
            return false;
        }

        for i in start_pos..SUDOKU_CELL_SIZE {
            let count = self.cells[i].count_candidates();
            match count {
                0 => return false,
                1 => continue,
                _ => (),
            }

            for candidate in 0..(SUDOKU_CANDIDATE_SIZE as SudokuCandidate) {
                let mut target_cell = self.cells[i].clone();
                if target_cell.can_mask(candidate) {
                    let mut new_map = SudokuMap::new("");
                    new_map.cells = self.cells.clone();
                    new_map.cells[i].overwrite_candidate(candidate);
                    if new_map.solve_from(start_pos + 1) {
                        self.cells = new_map.cells;
                        return true;
                    }
                }
            }
        }

        self.is_solved()
    }

    fn filter_unique_candidates(&mut self) {
        let mut group_gen = SudokuGroupGen::new();
        while let Some(indexes) = group_gen.next() {
            let froms = indexes.clone();
            for index in froms {
                let cell = self.cells[index];
                let targets = indexes.clone();
                for target in targets {
                    if target != index {
                        self.cells[target].mask_candidate(&cell);
                    }
                }
            }
        }
    }

    fn is_solved(&self) -> bool {
        let mut group_gen = SudokuGroupGen::new();
        while let Some(indexes) = group_gen.next() {
            if !self.is_group_solved(indexes) {
                return false;
            }
        }
        true
    }

    fn is_group_solved(&self, cell_indexes: Vec<usize>) -> bool {
        let mut sum = SudokuCell::new();
        let mut conflict = false;
        sum.clear_candidate();
        for cell_index in cell_indexes {
            conflict |= sum.merge_unique_candidate(&self.cells[cell_index]);
        }
        sum.has_all_candidates() && !conflict
    }

    fn is_consistent(&self) -> bool {
        let mut group_gen = SudokuGroupGen::new();
        while let Some(indexes) = group_gen.next() {
            if !self.is_group_consistent(indexes) {
                return false;
            }
        }
        true
    }

    fn is_group_consistent(&self, cell_indexes: Vec<usize>) -> bool {
        let mut all_candidates = SudokuCell::new();
        let mut unique_candidates = SudokuCell::new();
        let mut conflict = false;
        all_candidates.clear_candidate();
        unique_candidates.clear_candidate();

        for cell_index in cell_indexes {
            all_candidates.merge_candidate(&self.cells[cell_index]);
            conflict |= unique_candidates.merge_unique_candidate(&self.cells[cell_index]);
        }
        all_candidates.has_all_candidates() && !conflict
    }
}

fn main() {
    let stdin = io::stdin();

    for line in stdin.lock().lines() {
        let line = line.unwrap();
        let mut sudoku_map = SudokuMap::new(&line);
        let result = sudoku_map.solve();
        let answer = sudoku_map.to_string();
        if result {
            println!("Solved\n{}", answer);
        } else {
            println!("Not solved\n{}", answer);
        }
    }
}
<commit_msg>Remove an intentional underflow<commit_after>use std::io;
use std::io::prelude::*;

type SudokuCandidate = u64;
const SUDOKU_DIGIT_BASE: u32 = 10;
const SUDOKU_CANDIDATE_SIZE: usize = 9;
const SUDOKU_BOX_SIZE: usize = 3;
const SUDOKU_GROUP_SIZE: usize = 9;
const SUDOKU_CELL_SIZE: usize = 81;
const SUDOKU_ALL_CANDIDATES: SudokuCandidate = ((1 << SUDOKU_CANDIDATE_SIZE) - 1);

// Sudoku cell that contains candidates as a bitboard
#[derive(Clone, Copy)]
struct SudokuCell {
    candidates: SudokuCandidate
}

impl SudokuCell {
    fn new() -> SudokuCell {
        SudokuCell { candidates: SUDOKU_ALL_CANDIDATES }
    }

    fn to_string(&self) -> String {
        let mut line = String::new();
        for candidate in 0..(SUDOKU_CANDIDATE_SIZE as SudokuCandidate) {
            if self.has_candidate(&candidate) {
                line.push_str(&(candidate+1).to_string());
            }
        }
        line
    }

    // Input '1'..'9'
    fn preset_candidate(&mut self, ch: char) {
        let code_digit_base = '1'.to_digit(SUDOKU_DIGIT_BASE).unwrap();
        match ch {
            '1'...'9' => {
                let number = (ch.to_digit(SUDOKU_DIGIT_BASE).unwrap() - code_digit_base) as SudokuCandidate;
                self.candidates = self.digit_to_candidate(&number);
            }
            _ => {}
        }
    }

    fn clear_candidate(&mut self) {
        self.candidates = 0;
    }

    // Input 0..8
    fn overwrite_candidate(&mut self, candidate: SudokuCandidate) {
        if self.count_candidates() > 1 {
            self.candidates = self.digit_to_candidate(&candidate);
        }
    }

    fn count_candidates(&self) -> usize {
        let f = |candidate| {
            if (self.candidates & self.digit_to_candidate(&candidate))
                != 0 { 1 } else { 0 } };
        (0..SUDOKU_CANDIDATE_SIZE as SudokuCandidate).fold(
            0, |sum, candidates| sum + f(candidates))
    }

    fn has_unique_candidate(&self) -> bool {
        // Check whether only one bit is set
        self.candidates > 0 && (self.candidates & (self.candidates - 1)) == 0
    }

    fn has_all_candidates(&self) -> bool {
        self.candidates == SUDOKU_ALL_CANDIDATES
    }

    // Input 0..8
    fn can_mask(&mut self, candidates: SudokuCandidate) -> bool {
        (self.candidates & self.digit_to_candidate(&candidates)) != 0
    }

    fn mask_candidate(&mut self, rhs: &SudokuCell) {
        if rhs.count_candidates() == 1 {
            self.candidates &= !rhs.candidates;
        }
    }

    fn merge_candidate(&mut self, rhs: &SudokuCell) {
        self.candidates |= rhs.candidates;
    }

    // Returns whether no candidates are merged
    fn merge_unique_candidate(&mut self, rhs: &SudokuCell) -> bool {
        if rhs.has_unique_candidate() {
            if (self.candidates & rhs.candidates) != 0 {
                return true;
            }
            self.candidates |= rhs.candidates;
        }
        false
    }

    // Inner methods
    // Input 0..8
    fn digit_to_candidate(&self, candidate: &SudokuCandidate) -> SudokuCandidate {
        (1 as SudokuCandidate) << candidate
    }

    // Input 0..8
    fn has_candidate(&self, candidate: &SudokuCandidate) -> bool {
        (self.candidates & self.digit_to_candidate(&candidate)) != 0
    }
}

// Generator for sudoku cellgroups
struct SudokuGroupGen {
    index: usize
}

impl SudokuGroupGen {
    fn new() -> SudokuGroupGen {
        SudokuGroupGen { index:0 }
    }

    fn next(&mut self) -> Option<Vec<usize>> {
        if self.index < SUDOKU_GROUP_SIZE {
            let lower = self.index * SUDOKU_GROUP_SIZE;
            let upper = (self.index + 1) * SUDOKU_GROUP_SIZE;
            self.index += 1;
            Some((lower..upper).collect::<Vec<_>>())
        } else if self.index < (SUDOKU_GROUP_SIZE * 2) {
            let column = self.index - SUDOKU_GROUP_SIZE;
            self.index += 1;
            Some((0..SUDOKU_GROUP_SIZE).map(|i| column + i * SUDOKU_GROUP_SIZE).collect::<Vec<_>>())
        } else if self.index < (SUDOKU_GROUP_SIZE * 3) {
            let box_index = self.index - SUDOKU_GROUP_SIZE * 2;
            let offset = (box_index % 3) * 3  + (box_index / 3) * SUDOKU_GROUP_SIZE * 3;
            let mut indexes : Vec<usize> = Vec::new();
            for row in 0..SUDOKU_BOX_SIZE {
                let x = (0..SUDOKU_BOX_SIZE).map(|column| row * SUDOKU_GROUP_SIZE + column + offset).collect::<Vec<_>>();
                indexes.extend(x);
            }
            self.index += 1;
            Some(indexes)
        } else {
            None
        }
    }
}

// Sudoku cell map
struct SudokuMap {
    cells : Vec<SudokuCell>
}

impl SudokuMap {
    fn new(line: &str) -> SudokuMap {
        let mut cells = vec![SudokuCell::new(); SUDOKU_CELL_SIZE];
        for (index, ch) in line.chars().enumerate() {
            cells[index].preset_candidate(ch);
        }
        SudokuMap { cells:cells }
    }

    fn to_string(&self) -> String {
        let mut full_text = String::new();

        for row in 0..SUDOKU_GROUP_SIZE {
            let mut line = String::new();
            for column in 0..SUDOKU_GROUP_SIZE {
                let index = row * SUDOKU_GROUP_SIZE + column;
                let cell_str = self.cells[index].to_string();
                line.push_str(&cell_str);
                line.push_str(":");
            }
            line.push_str("\n");
            full_text.push_str(&line);
        }
        full_text
    }

    fn solve(&mut self) -> bool {
        self.solve_from(0)
    }

    fn solve_from(&mut self, start_pos : usize) -> bool {
        self.filter_unique_candidates();
        if !self.is_consistent() {
            return false;
        }

        for i in start_pos..SUDOKU_CELL_SIZE {
            let count = self.cells[i].count_candidates();
            match count {
                0 => return false,
                1 => continue,
                _ => (),
            }

            for candidate in 0..(SUDOKU_CANDIDATE_SIZE as SudokuCandidate) {
                let mut target_cell = self.cells[i].clone();
                if target_cell.can_mask(candidate) {
                    let mut new_map = SudokuMap::new("");
                    new_map.cells = self.cells.clone();
                    new_map.cells[i].overwrite_candidate(candidate);
                    if new_map.solve_from(start_pos + 1) {
                        self.cells = new_map.cells;
                        return true;
                    }
                }
            }
        }

        self.is_solved()
    }

    fn filter_unique_candidates(&mut self) {
        let mut group_gen = SudokuGroupGen::new();
        while let Some(indexes) = group_gen.next() {
            let froms = indexes.clone();
            for index in froms {
                let cell = self.cells[index];
                let targets = indexes.clone();
                for target in targets {
                    if target != index {
                        self.cells[target].mask_candidate(&cell);
                    }
                }
            }
        }
    }

    fn is_solved(&self) -> bool {
        let mut group_gen = SudokuGroupGen::new();
        while let Some(indexes) = group_gen.next() {
            if !self.is_group_solved(indexes) {
                return false;
            }
        }
        true
    }

    fn is_group_solved(&self, cell_indexes: Vec<usize>) -> bool {
        let mut sum = SudokuCell::new();
        let mut conflict = false;
        sum.clear_candidate();
        for cell_index in cell_indexes {
            conflict |= sum.merge_unique_candidate(&self.cells[cell_index]);
        }
        sum.has_all_candidates() && !conflict
    }

    fn is_consistent(&self) -> bool {
        let mut group_gen = SudokuGroupGen::new();
        while let Some(indexes) = group_gen.next() {
            if !self.is_group_consistent(indexes) {
                return false;
            }
        }
        true
    }

    fn is_group_consistent(&self, cell_indexes: Vec<usize>) -> bool {
        let mut all_candidates = SudokuCell::new();
        let mut unique_candidates = SudokuCell::new();
        let mut conflict = false;
        all_candidates.clear_candidate();
        unique_candidates.clear_candidate();

        for cell_index in cell_indexes {
            all_candidates.merge_candidate(&self.cells[cell_index]);
            conflict |= unique_candidates.merge_unique_candidate(&self.cells[cell_index]);
        }
        all_candidates.has_all_candidates() && !conflict
    }
}

fn main() {
    let stdin = io::stdin();

    for line in stdin.lock().lines() {
        let line = line.unwrap();
        let mut sudoku_map = SudokuMap::new(&line);
        let result = sudoku_map.solve();
        let answer = sudoku_map.to_string();
        if result {
            println!("Solved\n{}", answer);
        } else {
            println!("Not solved\n{}", answer);
        }
    }
}
<|endoftext|>