i64.move 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. module pyth::i64 {
  2. use pyth::error;
  3. const MAX_MAGNITUDE: u64 = (1 << 63) - 1;
  4. /// As Move does not support negative numbers natively, we use our own internal
  5. /// representation.
  6. struct I64 has copy, drop, store {
  7. negative: bool,
  8. magnitude: u64,
  9. }
  10. public fun new(magnitude: u64, negative: bool): I64 {
  11. assert!(magnitude <= MAX_MAGNITUDE, error::magnitude_too_large());
  12. I64 {
  13. magnitude: magnitude,
  14. negative: negative,
  15. }
  16. }
  17. public fun get_is_negative(i: &I64): bool {
  18. i.negative
  19. }
  20. public fun get_magnitude(in: &I64): u64 {
  21. in.magnitude
  22. }
  23. public fun get_magnitude_if_positive(in: &I64): u64 {
  24. assert!(!in.negative, error::negative_value());
  25. in.magnitude
  26. }
  27. public fun get_magnitude_if_negative(in: &I64): u64 {
  28. assert!(in.negative, error::positive_value());
  29. in.magnitude
  30. }
  31. public fun from_u64(from: u64): I64 {
  32. // Use the MSB to determine whether the number is negative or not.
  33. let negative = (from >> 63) == 1;
  34. return I64 {
  35. negative: negative,
  36. magnitude: parse_magnitude(from, negative),
  37. }
  38. }
  39. fun parse_magnitude(from: u64, negative: bool): u64 {
  40. // If positive, then return the input verbatamin
  41. if (!negative) {
  42. return from
  43. };
  44. // Otherwise convert from two's complement by inverting and adding 1
  45. let inverted = from ^ 0xFFFFFFFFFFFFFFFF;
  46. inverted + 1
  47. }
  48. #[test]
  49. #[expected_failure(abort_code = 65557)]
  50. fun test_magnitude_too_large() {
  51. new(0x8000000000000000, false);
  52. }
  53. #[test]
  54. fun test_from_u64_positive() {
  55. assert!(from_u64(0x64673) == new(0x64673, false), 1);
  56. }
  57. #[test]
  58. fun test_from_u64_negative() {
  59. assert!(from_u64(0xFFFFFFFFFFFEDC73) == new(0x1238D, true), 1);
  60. }
  61. #[test]
  62. fun test_get_is_negative() {
  63. assert!(get_is_negative(&new(234, true)) == true, 1);
  64. assert!(get_is_negative(&new(767, false)) == false, 1);
  65. }
  66. #[test]
  67. fun test_get_magnitude() {
  68. assert!(get_magnitude(&new(234, false)) == 234, 1);
  69. }
  70. #[test]
  71. fun test_get_magnitude_if_positive_positive() {
  72. assert!(get_magnitude_if_positive(&new(7686, false)) == 7686, 1);
  73. }
  74. #[test]
  75. #[expected_failure(abort_code = 196609)]
  76. fun test_get_magnitude_if_positive_negative() {
  77. assert!(get_magnitude_if_positive(&new(7686, true)) == 7686, 1);
  78. }
  79. #[test]
  80. fun test_get_magnitude_if_negative_negative() {
  81. assert!(get_magnitude_if_negative(&new(7686, true)) == 7686, 1);
  82. }
  83. #[test]
  84. #[expected_failure(abort_code = 196627)]
  85. fun test_get_magnitude_if_negative_positive() {
  86. assert!(get_magnitude_if_negative(&new(7686, false)) == 7686, 1);
  87. }
  88. }