1pub mod xmat;
4
5use crate::core::*;
6use std::{result::Result, error::Error};
8use std::{ffi};
9
10pub const D3DX_PI: f32 = std::f32::consts::PI;
12
13#[inline]
15pub fn rad(a: f32) -> f32 {
16 a * D3DX_PI / 180.0f32 }
18
19pub fn normalize_deg(a: f32) -> f32 {
21 let p = 180.0f32;
22 let p2 = 2.0f32 * p;
23 let mut a = a;
24 while a > p { a -= p2 }
25 while a < -p { a += p2 }
26 a
27}
28
29pub fn normalize_rad(th: f32) -> f32 {
31 let pi = std::f32::consts::PI;
32 let pi2 = 2.0f32 * pi;
33 let mut th = th;
34 while th > pi { th -= pi2 }
35 while th < -pi { th += pi2 }
36 th
37}
38
39#[inline]
41pub fn prec_eq(a: f32, b: f32, p: f32) -> bool {
42 prec_diff(a, b, p) == 0.0f32
43}
44
45pub fn prec_diff(a: f32, b: f32, p: f32) -> f32 {
47 if a == b { 0.0 }
48 else {
49 let f = a - b;
50 if f > 0.0 { if p > f { 0.0 } else { f } }
51 else { if p > -f { 0.0 } else { f } }
52 }
53}
54
55#[macro_export]
57macro_rules! toarray {
58 ($o:expr) => { $o.collect::<Vec<_>>().try_into().expect("toarray") };
59}
60pub use toarray;
61
62#[derive(Clone)]
64pub struct XV2ULL (pub [ffi::c_ulonglong; 2]);
65
66impl Ptr<u64> for XV2ULL {
68 #[inline]
70 fn ptr(&self) -> *const u64 { self as *const XV2ULL as *const u64 }
71 #[inline]
73 fn ptr_mut(&mut self) -> *mut u64 { self as *mut XV2ULL as *mut u64 }
74}
75
76impl Dump for XV2ULL {
78 fn dump(&self) -> String {
80 let mut p = DispMatParam{m: self.voidp(), w: SZU64, rows: 1, cols: 2,
81 fmt: "%016llx\0".as_ptr(), di: 16, df: 0, r: 0, c: 0};
82 let f = cb_xll;
83 let mut s = [0u8; SZBUF];
84unsafe {
85 let l = disp_mat(&mut s as *mut u8, SZBUF, &mut p, Some(f));
86 String::from_utf8(s[..l].to_vec()).expect("utf8")
87}
88 }
89}
90
91impl Disp for XV2ULL {
93 fn disp(&self, di: usize, df: usize) -> String {
95 let fmt = format!("%{}llu\0", di).as_str().as_ptr();
96 let mut p = DispMatParam{m: self.voidp(), w: SZU64, rows: 1, cols: 2,
97 fmt, di, df, r: 0, c: 0};
98 let f = cb_u64; let mut s = [0u8; SZBUF];
100unsafe {
101 let l = disp_mat(&mut s as *mut u8, SZBUF, &mut p, Some(f));
102 String::from_utf8(s[..l].to_vec()).expect("utf8")
103}
104 }
105}
106
107impl std::fmt::Display for XV2ULL {
109 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
111 write!(f, "{}", self.disp(21, 0))
112 }
113}
114
115impl std::fmt::Debug for XV2ULL {
117 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
119 write!(f, "{}", self.disp(21, 0))
120 }
121}
122
123#[derive(Clone)]
125pub struct XV2LL (pub [ffi::c_longlong; 2]);
126
127impl Ptr<i64> for XV2LL {
129 #[inline]
131 fn ptr(&self) -> *const i64 { self as *const XV2LL as *const i64 }
132 #[inline]
134 fn ptr_mut(&mut self) -> *mut i64 { self as *mut XV2LL as *mut i64 }
135}
136
137impl Dump for XV2LL {
139 fn dump(&self) -> String {
141 let mut p = DispMatParam{m: self.voidp(), w: SZI64, rows: 1, cols: 2,
142 fmt: "%016llx\0".as_ptr(), di: 16, df: 0, r: 0, c: 0};
143 let f = cb_xll;
144 let mut s = [0u8; SZBUF];
145unsafe {
146 let l = disp_mat(&mut s as *mut u8, SZBUF, &mut p, Some(f));
147 String::from_utf8(s[..l].to_vec()).expect("utf8")
148}
149 }
150}
151
152impl Disp for XV2LL {
154 fn disp(&self, di: usize, df: usize) -> String {
156 let fmt = format!("%{}lld\0", di).as_str().as_ptr();
157 let mut p = DispMatParam{m: self.voidp(), w: SZI64, rows: 1, cols: 2,
158 fmt, di, df, r: 0, c: 0};
159 let f = cb_i64; let mut s = [0u8; SZBUF];
161unsafe {
162 let l = disp_mat(&mut s as *mut u8, SZBUF, &mut p, Some(f));
163 String::from_utf8(s[..l].to_vec()).expect("utf8")
164}
165 }
166}
167
168impl std::fmt::Display for XV2LL {
170 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
172 write!(f, "{}", self.disp(21, 0))
173 }
174}
175
176impl std::fmt::Debug for XV2LL {
178 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
180 write!(f, "{}", self.disp(21, 0))
181 }
182}
183
184#[derive(Clone)]
186pub struct XV2U (pub [ffi::c_uint; 2]);
187
188impl Ptr<u32> for XV2U {
190 #[inline]
192 fn ptr(&self) -> *const u32 { self as *const XV2U as *const u32 }
193 #[inline]
195 fn ptr_mut(&mut self) -> *mut u32 { self as *mut XV2U as *mut u32 }
196}
197
198impl Dump for XV2U {
200 fn dump(&self) -> String {
202 let mut p = DispMatParam{m: self.voidp(), w: SZU32, rows: 1, cols: 2,
203 fmt: "%08x\0".as_ptr(), di: 8, df: 0, r: 0, c: 0};
204 let f = cb_x;
205 let mut s = [0u8; SZBUF];
206unsafe {
207 let l = disp_mat(&mut s as *mut u8, SZBUF, &mut p, Some(f));
208 String::from_utf8(s[..l].to_vec()).expect("utf8")
209}
210 }
211}
212
213impl Disp for XV2U {
215 fn disp(&self, di: usize, df: usize) -> String {
217 let fmt = format!("%{}lu\0", di).as_str().as_ptr();
218 let mut p = DispMatParam{m: self.voidp(), w: SZU32, rows: 1, cols: 2,
219 fmt, di, df, r: 0, c: 0};
220 let f = cb_u32; let mut s = [0u8; SZBUF];
222unsafe {
223 let l = disp_mat(&mut s as *mut u8, SZBUF, &mut p, Some(f));
224 String::from_utf8(s[..l].to_vec()).expect("utf8")
225}
226 }
227}
228
229impl std::fmt::Display for XV2U {
231 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
233 write!(f, "{}", self.disp(17, 0))
234 }
235}
236
237impl std::fmt::Debug for XV2U {
239 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
241 write!(f, "{}", self.disp(17, 0))
242 }
243}
244
245#[derive(Clone)]
247pub struct XV2I (pub [ffi::c_int; 2]);
248
249impl Ptr<i32> for XV2I {
251 #[inline]
253 fn ptr(&self) -> *const i32 { self as *const XV2I as *const i32 }
254 #[inline]
256 fn ptr_mut(&mut self) -> *mut i32 { self as *mut XV2I as *mut i32 }
257}
258
259impl Dump for XV2I {
261 fn dump(&self) -> String {
263 let mut p = DispMatParam{m: self.voidp(), w: SZI32, rows: 1, cols: 2,
264 fmt: "%08x\0".as_ptr(), di: 8, df: 0, r: 0, c: 0};
265 let f = cb_x;
266 let mut s = [0u8; SZBUF];
267unsafe {
268 let l = disp_mat(&mut s as *mut u8, SZBUF, &mut p, Some(f));
269 String::from_utf8(s[..l].to_vec()).expect("utf8")
270}
271 }
272}
273
274impl Disp for XV2I {
276 fn disp(&self, di: usize, df: usize) -> String {
278 let fmt = format!("%{}ld\0", di).as_str().as_ptr();
279 let mut p = DispMatParam{m: self.voidp(), w: SZI32, rows: 1, cols: 2,
280 fmt, di, df, r: 0, c: 0};
281 let f = cb_i32; let mut s = [0u8; SZBUF];
283unsafe {
284 let l = disp_mat(&mut s as *mut u8, SZBUF, &mut p, Some(f));
285 String::from_utf8(s[..l].to_vec()).expect("utf8")
286}
287 }
288}
289
290impl std::fmt::Display for XV2I {
292 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
294 write!(f, "{}", self.disp(17, 0))
295 }
296}
297
298impl std::fmt::Debug for XV2I {
300 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
302 write!(f, "{}", self.disp(17, 0))
303 }
304}
305
306#[derive(Clone)]
308pub struct XV2F32 (pub [ffi::c_float; 2]);
309
310impl Ptr<f32> for XV2F32 {
312 #[inline]
314 fn ptr(&self) -> *const f32 { self as *const XV2F32 as *const f32 }
315 #[inline]
317 fn ptr_mut(&mut self) -> *mut f32 { self as *mut XV2F32 as *mut f32 }
318}
319
320impl Dump for XV2F32 {
322 fn dump(&self) -> String {
324 let mut p = DispMatParam{m: self.voidp(), w: SZF32, rows: 1, cols: 2,
325 fmt: "%08x\0".as_ptr(), di: 8, df: 0, r: 0, c: 0};
326 let f = cb_x;
327 let mut s = [0u8; SZBUF];
328unsafe {
329 let l = disp_mat(&mut s as *mut u8, SZBUF, &mut p, Some(f));
330 String::from_utf8(s[..l].to_vec()).expect("utf8")
331}
332 }
333}
334
335impl Disp for XV2F32 {
337 fn disp(&self, di: usize, df: usize) -> String {
339 let fmt = format!("%{}.{}f\0", di, df).as_str().as_ptr();
340 let mut p = DispMatParam{m: self.voidp(), w: SZF32, rows: 1, cols: 2,
341 fmt, di, df, r: 0, c: 0};
342 let f = cb_f32; let mut s = [0u8; SZBUF];
344unsafe {
345 let l = disp_mat(&mut s as *mut u8, SZBUF, &mut p, Some(f));
346 String::from_utf8(s[..l].to_vec()).expect("utf8")
347}
348 }
349}
350
351impl std::fmt::Display for XV2F32 {
353 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
355 write!(f, "{}", self.disp(17, 7))
356 }
357}
358
359impl std::fmt::Debug for XV2F32 {
361 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
363 write!(f, "{}", self.disp(17, 7))
364 }
365}
366
367#[derive(Clone)]
369pub struct XV3F32 (pub [ffi::c_float; 3]);
370
371impl XV3F32 {
373 #[inline]
375 pub fn o() -> Self {
376 XV3F32([0.0f32; 3])
377 }
378
379 pub fn prec_diff(&self, b: &Self, p: f32) -> Result<Self, Box<dyn Error>> {
381 Ok(XV3F32(
382toarray!(self.0.iter().zip(b.0.iter()).map(|(&f, &g)|
387 prec_diff(f, g, p)))
388 ))
389 }
390
391 #[inline]
393 pub fn prec_eq(&self, b: &Self, p: f32) ->
394 Result<bool, Box<dyn Error>> {
395 Ok(self.prec_diff(b, p)?.0 == XV3F32::o().0)
396 }
397
398 #[inline]
400 pub fn prec_eq_array(&self, b: &[f32; 3], p: f32) ->
401 Result<bool, Box<dyn Error>> {
402 self.prec_eq(&XV3F32(*b), p)
403 }
404
405 pub fn dot(&self, b: &Self) -> f32 {
407 self.0.iter().zip(b.0.iter()).map(|(&f, &g)| f * g).sum()
408 }
409
410 pub fn cross(&self, b: &Self) -> Self {
412 let [x0, y0, z0] = self.0;
413 let [x1, y1, z1] = b.0;
414 XV3F32([y0 * z1 - z0 * y1, z0 * x1 - x0 * z1, x0 * y1 - y0 * x1])
415 }
416
417 #[inline]
419 pub fn norm(&self, b: &Self) -> Result<Self, Box<dyn Error>> {
420 self.cross(b).normalize()
421 }
422
423 pub fn normalize(&self) -> Result<Self, Box<dyn Error>> {
425 let a = self.0;
426 let r = f32::sqrt(a.into_iter().map(|f| f * f).sum());
427 Ok(XV3F32(toarray!(a.into_iter().map(|f| f / r))))
428 }
429
430 #[inline]
432 pub fn set_normalize(&mut self) -> Result<&mut Self, Box<dyn Error>> {
433 self.0 = self.normalize()?.0;
434 Ok(self)
435 }
436}
437
438impl TryFrom<XV4F32> for XV3F32 {
440 type Error = Box<dyn Error>;
441
442 fn try_from(v: XV4F32) -> Result<Self, Self::Error> {
444 let v = v.0;
445 Ok(XV3F32([v[0], v[1], v[2]])) }
447}
448
449impl Ptr<f32> for XV3F32 {
451 #[inline]
453 fn ptr(&self) -> *const f32 { self as *const XV3F32 as *const f32 }
454 #[inline]
456 fn ptr_mut(&mut self) -> *mut f32 { self as *mut XV3F32 as *mut f32 }
457}
458
459impl Dump for XV3F32 {
461 fn dump(&self) -> String {
463 let mut p = DispMatParam{m: self.voidp(), w: SZF32, rows: 1, cols: 3,
464 fmt: "%08x\0".as_ptr(), di: 8, df: 0, r: 0, c: 0};
465 let f = cb_x;
466 let mut s = [0u8; SZBUF];
467unsafe {
468 let l = disp_mat(&mut s as *mut u8, SZBUF, &mut p, Some(f));
469 String::from_utf8(s[..l].to_vec()).expect("utf8")
470}
471 }
472}
473
474impl Disp for XV3F32 {
476 fn disp(&self, di: usize, df: usize) -> String {
478 let fmt = format!("%{}.{}f\0", di, df).as_str().as_ptr();
479 let mut p = DispMatParam{m: self.voidp(), w: SZF32, rows: 1, cols: 3,
480 fmt, di, df, r: 0, c: 0};
481 let f = cb_f32; let mut s = [0u8; SZBUF];
483unsafe {
484 let l = disp_mat(&mut s as *mut u8, SZBUF, &mut p, Some(f));
485 String::from_utf8(s[..l].to_vec()).expect("utf8")
486}
487 }
488}
489
490impl std::fmt::Display for XV3F32 {
492 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
494 write!(f, "{}", self.disp(17, 7))
495 }
496}
497
498impl std::fmt::Debug for XV3F32 {
500 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
502 write!(f, "{}", self.disp(17, 7))
503 }
504}
505
506#[derive(Clone)]
508pub struct XV4F32 (pub [ffi::c_float; 4]);
509
510impl XV4F32 {
512 #[inline]
514 pub fn o() -> Self {
515 XV4F32([0.0f32; 4])
516 }
517
518 #[inline]
520 pub fn i() -> Self {
521 XV4F32([0.0f32, 0.0f32, 0.0f32, 1.0f32])
522 }
523
524 pub fn prec_diff(&self, b: &Self, p: f32) -> Result<Self, Box<dyn Error>> {
526 Ok(XV4F32(
527toarray!(self.0.iter().zip(b.0.iter()).map(|(&f, &g)|
532 prec_diff(f, g, p)))
533 ))
534 }
535
536 #[inline]
538 pub fn prec_eq(&self, b: &Self, p: f32) ->
539 Result<bool, Box<dyn Error>> {
540 Ok(self.prec_diff(b, p)?.0 == XV4F32::o().0)
541 }
542
543 #[inline]
545 pub fn prec_eq_array(&self, b: &[f32; 4], p: f32) ->
546 Result<bool, Box<dyn Error>> {
547 self.prec_eq(&XV4F32(*b), p)
548 }
549
550 pub fn dot(self, b: &Self) -> f32 {
552 self.0.iter().zip(b.0.iter()).map(|(&f, &g)| f * g).sum()
553 }
554
555 pub fn cross3(self, b: &Self) -> Self {
557 let [x0, y0, z0, _w0] = self.0;
558 let [x1, y1, z1, _w1] = b.0;
559 let w = 1.0f32; XV4F32([y0 * z1 - z0 * y1, z0 * x1 - x0 * z1, x0 * y1 - y0 * x1, w])
561 }
562
563 #[inline]
565 pub fn norm3(self, b: &Self) -> Result<Self, Box<dyn Error>> {
566 self.cross3(b).normalize3()
567 }
568
569 #[inline]
571 pub fn normalize3(self) -> Result<Self, Box<dyn Error>> {
572 XV4F32::try_from(XV3F32::try_from(self)?.normalize()?)
573 }
574
575 pub fn normalize(&self) -> Result<Self, Box<dyn Error>> {
577 let mut q = Self::o();
578unsafe {
579 if isnull!(D3DXQuaternionNormalize(
580 q.ptr_mut() as *mut D3DXQUATERNION,
581 self.ptr() as *const D3DXQUATERNION
582 )) { Err("normalize".into()) }
583 else { Ok(q) }
584}
585 }
586
587 pub fn set_normalize(&mut self) -> Result<&mut Self, Box<dyn Error>> {
589unsafe {
590 if isnull!(D3DXQuaternionNormalize(
591 self.ptr_mut() as *mut D3DXQUATERNION,
592 self.ptr() as *const D3DXQUATERNION
593 )) { Err("set_normalize".into()) }
594 else { Ok(self) }
595}
596 }
597
598 pub fn inverse(&self) -> Result<Self, Box<dyn Error>> {
600 let mut q = Self::o();
601unsafe {
602 if isnull!(D3DXQuaternionInverse(
603 q.ptr_mut() as *mut D3DXQUATERNION,
604 self.ptr() as *const D3DXQUATERNION
605 )) { Err("inverse".into()) }
606 else { Ok(q) }
607}
608 }
609
610 #[inline]
612 pub fn conjugate(&self) -> Result<Self, Box<dyn Error>> {
613 let q = self.0;
614 Ok(XV4F32([-q[0], -q[1], -q[2], q[3]]))
615}
617
618 pub fn quaternion(axis: &XV3F32, th: f32) -> Result<Self, Box<dyn Error>> {
620 let a = axis.normalize()?.0;
621 let r = th / 2.0f32;
622 let c = f32::cos(r);
623 let s = f32::sin(r);
624 Ok(XV4F32([a[0] * s, a[1] * s, a[2] * s, c]))
625}
627
628 pub fn quaternion_m(m: &XMat44F32, prec: f32) ->
630 Result<Self, Box<dyn Error>> {
631 let q = m.transpose()?.0; let (xs, ys, zs, c); let cc = (q[0][0] + q[1][1] + q[2][2] + q[3][3]) / 4.0f32;
634 if prec_eq(cc, 0.0f32, prec) {
635 c = 0.0f32;
636 let xsxs = - (q[1][1] + q[2][2]) / 2.0f32;
637 if prec_eq(xsxs, 0.0f32, prec) {
638 xs = 0.0f32;
639 let ysys = (q[3][3] - q[2][2]) / 2.0f32;
640 if prec_eq(ysys, 0.0f32, prec) {
641 ys = 0.0f32;
642 zs = 1.0f32;
643 }else if ysys > 0.0f32 {
644 ys = f32::sqrt(ysys); zs = q[1][2] / (ys * 2.0f32);
646 }else{ return Err("not a rotation matrix".into());
648 }
649 }else if xsxs > 0.0f32 {
650 xs = f32::sqrt(xsxs); let xs2 = xs * 2.0f32;
652 ys = q[0][1] / xs2;
653 zs = q[0][2] / xs2;
654 }else{ return Err("not a rotation matrix".into());
656 }
657 }else if cc > 0.0f32 {
658 c = f32::sqrt(cc); let c4 = c * 4.0f32;
660 xs = (q[2][1] - q[1][2]) / c4;
661 ys = (q[0][2] - q[2][0]) / c4;
662 zs = (q[1][0] - q[0][1]) / c4;
663 }else{ return Err("not a rotation matrix".into());
665 }
666 Ok(XV4F32([xs, ys, zs, c]))
667 }
668
669 pub fn rotation_axis(axis: &XV3F32, th: f32) ->
671 Result<Self, Box<dyn Error>> {
672 let mut q = Self::o();
673unsafe {
674 if isnull!(D3DXQuaternionRotationAxis(
675 q.ptr_mut() as *mut D3DXQUATERNION,
676 axis.ptr() as *const D3DXVECTOR3,
677 th
678 )) { Err("quaternion rotation axis".into()) }
679 else { Ok(q) }
680}
681 }
682
683 pub fn set_rotation_axis(&mut self, axis: &XV3F32, th: f32) ->
685 Result<&mut Self, Box<dyn Error>> {
686unsafe {
687 if isnull!(D3DXQuaternionRotationAxis(
688 self.ptr_mut() as *mut D3DXQUATERNION,
689 axis.ptr() as *const D3DXVECTOR3,
690 th
691 )) { Err("quaternion set rotation axis".into()) }
692 else { Ok(self) }
693}
694 }
695
696 #[inline]
700 pub fn mul(&self, b: &Self) ->
701 Result<Self, Box<dyn Error>> {
702 XMat44F32::quaternion_r(self)?.mulmv(b) }
706
707 pub fn q_mul(&self, b: &Self) ->
709 Result<Self, Box<dyn Error>> {
710 let mut q = Self::o();
711unsafe {
712 if isnull!(D3DXQuaternionMultiply(
713 q.ptr_mut() as *mut D3DXQUATERNION,
714 self.ptr() as *const D3DXQUATERNION,
715 b.ptr() as *const D3DXQUATERNION
716 )) { Err("quaternion multiply".into()) }
717 else { Ok(q) }
718}
719 }
720
721 pub fn set_q_mul(&mut self, b: &Self) ->
723 Result<&mut Self, Box<dyn Error>> {
724unsafe {
725 if isnull!(D3DXQuaternionMultiply(
726 self.ptr_mut() as *mut D3DXQUATERNION,
727 self.ptr() as *const D3DXQUATERNION,
728 b.ptr() as *const D3DXQUATERNION
729 )) { Err("set_q_mul".into()) }
730 else { Ok(self) }
731}
732 }
733}
734
735impl TryFrom<XMat44F32> for XV4F32 {
737 type Error = Box<dyn Error>;
738
739 fn try_from(m: XMat44F32) -> Result<Self, Self::Error> {
741 let mut q = Self::o();
742unsafe {
743 if isnull!(D3DXQuaternionRotationMatrix(
744 q.ptr_mut() as *mut D3DXQUATERNION,
745 m.ptr() as *const D3DXMATRIX
746 )) { Err("quaternion rotation matrix".into()) }
747 else { Ok(q) }
748}
749 }
750}
751
752impl TryFrom<XV3F32> for XV4F32 {
754 type Error = Box<dyn Error>;
755
756 fn try_from(v: XV3F32) -> Result<Self, Self::Error> {
758 let v = v.0;
759 Ok(XV4F32([v[0], v[1], v[2], 1.0f32])) }
761}
762
763impl Ptr<f32> for XV4F32 {
765 #[inline]
767 fn ptr(&self) -> *const f32 { self as *const XV4F32 as *const f32 }
768 #[inline]
770 fn ptr_mut(&mut self) -> *mut f32 { self as *mut XV4F32 as *mut f32 }
771}
772
773impl Dump for XV4F32 {
775 fn dump(&self) -> String {
777 let mut p = DispMatParam{m: self.voidp(), w: SZF32, rows: 1, cols: 4,
778 fmt: "%08x\0".as_ptr(), di: 8, df: 0, r: 0, c: 0};
779 let f = cb_x;
780 let mut s = [0u8; SZBUF];
781unsafe {
782 let l = disp_mat(&mut s as *mut u8, SZBUF, &mut p, Some(f));
783 String::from_utf8(s[..l].to_vec()).expect("utf8")
784}
785 }
786}
787
788impl Disp for XV4F32 {
790 fn disp(&self, di: usize, df: usize) -> String {
792 let fmt = format!("%{}.{}f\0", di, df).as_str().as_ptr();
793 let mut p = DispMatParam{m: self.voidp(), w: SZF32, rows: 1, cols: 4,
794 fmt, di, df, r: 0, c: 0};
795 let f = cb_f32; let mut s = [0u8; SZBUF];
797unsafe {
798 let l = disp_mat(&mut s as *mut u8, SZBUF, &mut p, Some(f));
799 String::from_utf8(s[..l].to_vec()).expect("utf8")
800}
801 }
802}
803
804impl std::fmt::Display for XV4F32 {
806 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
808 write!(f, "{}", self.disp(17, 7))
809 }
810}
811
812impl std::fmt::Debug for XV4F32 {
814 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
816 write!(f, "{}", self.disp(17, 7))
817 }
818}