Skip to content

Commit

Permalink
Raw pointer!
Browse files Browse the repository at this point in the history
  • Loading branch information
lgarron committed Aug 23, 2023
1 parent 52342a7 commit 8333b3c
Show file tree
Hide file tree
Showing 4 changed files with 168 additions and 98 deletions.
88 changes: 30 additions & 58 deletions examples/cpp_port/packed/packed_kpuzzle.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use std::{alloc::Layout, sync::Arc};

use cubing::{
alg::Move,
kpuzzle::{InvalidAlgError, InvalidDefinitionError, KPuzzle, KPuzzleOrbitName},
Expand All @@ -6,9 +8,10 @@ use cubing::{
use super::{PackedKState, PackedKTransformation};

#[derive(Debug, Clone)]
pub struct PackedKPuzzleOrbitData {
pub struct PackedKPuzzleOrbitInfo {
pub name: KPuzzleOrbitName,
pub bytes_offset: usize,
pub pieces_or_pemutations_offset: usize,
pub orientations_offset: usize,
pub num_pieces: usize,
pub num_orientations: u8,
pub unknown_orientation_value: u8,
Expand All @@ -20,15 +23,16 @@ pub struct PackedKPuzzleData {
pub kpuzzle: KPuzzle,
// Private cached values.
pub num_bytes: usize,
pub orbit_iteration_info: Vec<PackedKPuzzleOrbitData>,
pub orbit_iteration_info: Vec<PackedKPuzzleOrbitInfo>,
pub layout: Layout,
}

const X: u8 = 255;

#[derive(Debug, Clone)]
pub struct PackedKPuzzle {
// pub data: Arc<PackedKPuzzleData>, // TODO
pub data: PackedKPuzzleData,
pub data: Arc<PackedKPuzzleData>, // TODO
// pub data: PackedKPuzzleData,
}

impl TryFrom<KPuzzle> for PackedKPuzzle {
Expand All @@ -40,7 +44,7 @@ impl TryFrom<KPuzzle> for PackedKPuzzle {
let orbit_ordering = orbit_ordering.as_ref().ok_or_else(|| InvalidDefinitionError{ description: "Constructing a `PackedKPuzzle` from a `KPuzzle` requires the `orbitOrdering` field.".to_owned()})?;

let mut bytes_offset = 0;
let mut orbit_iteration_info: Vec<PackedKPuzzleOrbitData> = vec![];
let mut orbit_iteration_info: Vec<PackedKPuzzleOrbitInfo> = vec![];

for orbit_name in orbit_ordering {
let orbit_definition = kpuzzle.definition().orbits.get(orbit_name);
Expand All @@ -66,11 +70,13 @@ impl TryFrom<KPuzzle> for PackedKPuzzle {
}
};
orbit_iteration_info.push({
PackedKPuzzleOrbitData {
PackedKPuzzleOrbitInfo {
name: orbit_name.clone(),
num_pieces: orbit_definition.num_pieces,
num_orientations,
bytes_offset,
pieces_or_pemutations_offset: bytes_offset,
orientations_offset: bytes_offset
+ std::convert::Into::<usize>::into(orbit_definition.num_pieces),
unknown_orientation_value,
table,
}
Expand All @@ -79,10 +85,13 @@ impl TryFrom<KPuzzle> for PackedKPuzzle {
}

Ok(Self {
data: (PackedKPuzzleData {
data: Arc::new(PackedKPuzzleData {
kpuzzle,
num_bytes: bytes_offset,
orbit_iteration_info,
layout: Layout::array::<u8>(bytes_offset).map_err(|_| InvalidDefinitionError {
description: "Could not construct packed layout.".to_owned(),
})?,
}),
})
}
Expand All @@ -99,59 +108,24 @@ fn usize_to_u8(n: usize) -> u8 {
n.try_into().expect("Value too large!") // TODO
}

#[macro_export]
macro_rules! set_packed_piece_or_permutation {
($bytes:expr, $orbit_info:expr, $i:expr, $value: expr) => {
$bytes[$orbit_info.bytes_offset + $i] = ($value)
};
}

#[macro_export]
macro_rules! set_packed_orientation {
($bytes:expr, $orbit_info:expr, $i:expr, $value: expr) => {
$bytes[$orbit_info.bytes_offset + $orbit_info.num_pieces + $i] = ($value)
};
}

#[macro_export]
macro_rules! set_packed_piece_or_permutation_and_orientation {
($bytes:expr, $orbit_info:expr, $i:expr, $piece_or_permutation: expr, $orientation: expr) => {
set_packed_piece_or_permutation!($bytes, $orbit_info, $i, $piece_or_permutation);
set_packed_orientation!($bytes, $orbit_info, $i, $orientation);
};
}

#[macro_export]
macro_rules! get_packed_piece_or_permutation {
($bytes:expr, $orbit_info:expr, $i:expr) => {
$bytes[$orbit_info.bytes_offset + $i]
};
}

// Applies to both states and transformations.
#[macro_export]
macro_rules! get_packed_orientation {
($bytes:expr, $orbit_info:expr, $i:expr) => {
$bytes[$orbit_info.bytes_offset + $orbit_info.num_pieces + $i]
};
}

impl PackedKPuzzle {
pub fn start_state(&self) -> PackedKState {
let kstate_start_state_data = self.data.kpuzzle.start_state().state_data;
let mut bytes: [u8; 52] = [0; 52];

let new_state = PackedKState::new(self.clone());
for orbit_info in &self.data.orbit_iteration_info {
let kstate_orbit_data = kstate_start_state_data
.get(&orbit_info.name)
.expect("Missing orbit!");
let num_pieces = orbit_info.num_pieces;
for i in 0..num_pieces {
set_packed_piece_or_permutation_and_orientation!(
bytes,
for i in 0..orbit_info.num_pieces {
new_state.set_piece_or_permutation(
orbit_info,
i,
usize_to_u8(kstate_orbit_data.pieces[i]),
);
new_state.set_orientation(
orbit_info,
i,
match &kstate_orbit_data.orientation_mod {
None => usize_to_u8(kstate_orbit_data.orientation[i]),
Some(orientation_mod) => {
Expand All @@ -161,12 +135,12 @@ impl PackedKPuzzle {
_ => panic!("Unsupported!"), // TODO
}
}
}
},
);
}
}

PackedKState { bytes }
new_state
}

// TODO: implement this as a `TryFrom`?
Expand All @@ -176,7 +150,7 @@ impl PackedKPuzzle {
) -> Result<PackedKTransformation, ConversionError> {
let unpacked_ktransformation = self.data.kpuzzle.transformation_from_move(key_move)?;

let mut bytes: Vec<u8> = vec![0; self.data.num_bytes];
let new_transformation = PackedKTransformation::new(self.clone());
for orbit_info in &self.data.orbit_iteration_info {
let unpacked_orbit_data = unpacked_ktransformation
.transformation_data
Expand All @@ -186,16 +160,14 @@ impl PackedKPuzzle {
description: format!("Missing orbit: {}", orbit_info.name),
})?;
for i in 0..orbit_info.num_pieces {
set_packed_piece_or_permutation_and_orientation!(
bytes,
new_transformation.set_piece_or_permutation(
orbit_info,
i,
usize_to_u8(unpacked_orbit_data.permutation[i]),
usize_to_u8(unpacked_orbit_data.orientation[i])
);
}
}

Ok(PackedKTransformation { bytes })
Ok(new_transformation)
}
}
96 changes: 69 additions & 27 deletions examples/cpp_port/packed/packed_kstate.rs
Original file line number Diff line number Diff line change
@@ -1,53 +1,95 @@
use crate::{
get_packed_orientation, get_packed_piece_or_permutation, set_packed_orientation,
set_packed_piece_or_permutation, set_packed_piece_or_permutation_and_orientation,
};
use std::alloc::{alloc, dealloc};

use super::{PackedKPuzzle, PackedKTransformation};
use super::{packed_kpuzzle::PackedKPuzzleOrbitInfo, PackedKPuzzle, PackedKTransformation};

pub struct PackedKState {
// pub packed_kpuzzle: PackedKPuzzle,
pub bytes: [u8; 52],
pub packed_kpuzzle: PackedKPuzzle,
// pub bytes: [u8; 52],
pub bytes: *mut u8,
}

impl Drop for PackedKState {
fn drop(&mut self) {
unsafe { dealloc(self.bytes, self.packed_kpuzzle.data.layout) }
}
}

impl PackedKState {
pub fn new(packed_kpuzzle: PackedKPuzzle) -> Self {
let bytes = unsafe { alloc(packed_kpuzzle.data.layout) };
Self {
packed_kpuzzle,
bytes,
}
}

pub fn get_piece_or_permutation(&self, orbit_info: &PackedKPuzzleOrbitInfo, i: usize) -> u8 {
unsafe {
self.bytes
.add(orbit_info.pieces_or_pemutations_offset + i)
.read()
}
}

pub fn get_orientation(&self, orbit_info: &PackedKPuzzleOrbitInfo, i: usize) -> u8 {
unsafe { self.bytes.add(orbit_info.orientations_offset + i).read() }
}

pub fn set_piece_or_permutation(
&self,
orbit_info: &PackedKPuzzleOrbitInfo,
i: usize,
value: u8,
) {
unsafe {
self.bytes
.add(orbit_info.pieces_or_pemutations_offset + i)
.write(value)
}
}

pub fn set_orientation(&self, orbit_info: &PackedKPuzzleOrbitInfo, i: usize, value: u8) {
unsafe {
self.bytes
.add(orbit_info.orientations_offset + i)
.write(value)
}
}

// Adapted from https://github.com/cubing/cubing.rs/blob/b737c6a36528e9984b45b29f9449a9a330c272fb/src/kpuzzle/state.rs#L31-L82
// TODO: dedup the implementation (but avoid runtime overhead for the shared abstraction).
pub fn apply_transformation(
&self,
packed_kpuzzle: &PackedKPuzzle,
transformation: &PackedKTransformation,
) -> PackedKState {
let mut bytes: [u8; 52] = [0; 52];
let new_state = PackedKState::new(self.packed_kpuzzle.clone());
for orbit_info in &packed_kpuzzle.data.orbit_iteration_info {
// TODO: optimization when either value is the identity.
for i in 0..orbit_info.num_pieces {
let transformation_idx = std::convert::Into::<usize>::into(
get_packed_piece_or_permutation!(transformation.bytes, orbit_info, i),
let transformation_idx = transformation.get_piece_or_permutation(orbit_info, i);

let new_piece_permutation = self.get_piece_or_permutation(
orbit_info,
std::convert::Into::<usize>::into(transformation_idx),
);
self.set_piece_or_permutation(orbit_info, i, new_piece_permutation);

let new_piece_permutation =
get_packed_piece_or_permutation!(self.bytes, orbit_info, transformation_idx);
let previous_piece_orientation =
get_packed_orientation!(self.bytes, orbit_info, transformation_idx);
let new_piece_orientation = orbit_info.table[std::convert::Into::<usize>::into(
previous_piece_orientation
+ get_packed_orientation!(transformation.bytes, orbit_info, i),
)];
set_packed_piece_or_permutation_and_orientation!(
bytes,
let previous_piece_orientation = self.get_orientation(
orbit_info,
i,
new_piece_permutation,
new_piece_orientation
std::convert::Into::<usize>::into(transformation_idx),
);
let new_piece_orientation = orbit_info.table[std::convert::Into::<usize>::into(
previous_piece_orientation + transformation.get_orientation(orbit_info, i),
)];
self.set_orientation(orbit_info, i, new_piece_orientation);
}
}

PackedKState { bytes }
new_state
}

pub fn hash(&self) -> u64 {
cityhash::city_hash_64(&self.bytes)
}
// pub fn hash(&self) -> u64 {
// cityhash::city_hash_64(&self.bytes)
// }
}
58 changes: 57 additions & 1 deletion examples/cpp_port/packed/packed_ktransformation.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,59 @@
use std::alloc::{alloc, dealloc};

use super::{packed_kpuzzle::PackedKPuzzleOrbitInfo, PackedKPuzzle};
pub struct PackedKTransformation {
pub bytes: Vec<u8>,
pub packed_kpuzzle: PackedKPuzzle,
pub bytes: *mut u8,
}

impl Drop for PackedKTransformation {
fn drop(&mut self) {
unsafe { dealloc(self.bytes, self.packed_kpuzzle.data.layout) }
}
}

impl PackedKTransformation {
pub fn new(packed_kpuzzle: PackedKPuzzle) -> Self {
let bytes = unsafe { alloc(packed_kpuzzle.data.layout) };
Self {
packed_kpuzzle,
bytes,
}
}
// TODO: dedup with PackedKTransformation, or at least implement as a trait?
pub fn get_piece_or_permutation(&self, orbit_info: &PackedKPuzzleOrbitInfo, i: usize) -> u8 {
unsafe {
self.bytes
.add(orbit_info.pieces_or_pemutations_offset + i)
.read()
}
}

// TODO: dedup with PackedKTransformation, or at least implement as a trait?
pub fn get_orientation(&self, orbit_info: &PackedKPuzzleOrbitInfo, i: usize) -> u8 {
unsafe { self.bytes.add(orbit_info.orientations_offset + i).read() }
}

// TODO: dedup with PackedKTransformation, or at least implement as a trait?
pub fn set_piece_or_permutation(
&self,
orbit_info: &PackedKPuzzleOrbitInfo,
i: usize,
value: u8,
) {
unsafe {
self.bytes
.add(orbit_info.pieces_or_pemutations_offset + i)
.write(value)
}
}

// TODO: dedup with PackedKTransformation, or at least implement as a trait?
pub fn set_orientation(&self, orbit_info: &PackedKPuzzleOrbitInfo, i: usize, value: u8) {
unsafe {
self.bytes
.add(orbit_info.orientations_offset + i)
.write(value)
}
}
}
Loading

0 comments on commit 8333b3c

Please sign in to comment.