/ console / types / integers / src / to_scalar.rs
to_scalar.rs
  1  // Copyright (c) 2025-2026 ACDC Network
  2  // This file is part of the alphavm library.
  3  //
  4  // Alpha Chain | Delta Chain Protocol
  5  // International Monetary Graphite.
  6  //
  7  // Derived from Aleo (https://aleo.org) and ProvableHQ (https://provable.com).
  8  // They built world-class ZK infrastructure. We installed the EASY button.
  9  // Their cryptography: elegant. Our modifications: bureaucracy-compatible.
 10  // Original brilliance: theirs. Robert's Rules: ours. Bugs: definitely ours.
 11  //
 12  // Original Aleo/ProvableHQ code subject to Apache 2.0 https://www.apache.org/licenses/LICENSE-2.0
 13  // All modifications and new work: CC0 1.0 Universal Public Domain Dedication.
 14  // No rights reserved. No permission required. No warranty. No refunds.
 15  //
 16  // https://creativecommons.org/publicdomain/zero/1.0/
 17  // SPDX-License-Identifier: CC0-1.0
 18  
 19  use super::*;
 20  
 21  impl<E: Environment, I: IntegerType> Integer<E, I> {
 22      /// Converts an integer into a scalar.
 23      pub fn to_scalar(&self) -> Scalar<E> {
 24          // Note: We are reconstituting the integer as a scalar field.
 25          // This is safe as the number of bits in the integer is less than the scalar field modulus,
 26          // and thus will always fit within a single scalar field element.
 27          debug_assert!(I::BITS < Scalar::<E>::size_in_bits() as u64);
 28  
 29          // Reconstruct the bits as a linear combination representing the original value.
 30          let result = Scalar::from_bits_le(&self.to_bits_le());
 31          debug_assert!(result.is_ok(), "An integer should always be able to be constructed from scalar bits");
 32          result.unwrap()
 33      }
 34  }
 35  
 36  #[cfg(test)]
 37  mod tests {
 38      use super::*;
 39      use alphavm_console_network_environment::Console;
 40  
 41      type CurrentEnvironment = Console;
 42  
 43      const ITERATIONS: u64 = 10_000;
 44  
 45      fn check_to_scalar<I: IntegerType>() -> Result<()> {
 46          let mut rng = TestRng::default();
 47  
 48          for _ in 0..ITERATIONS {
 49              // Sample a random integer.
 50              let expected = Integer::<CurrentEnvironment, I>::rand(&mut rng);
 51  
 52              // Perform the operation.
 53              let candidate = expected.to_scalar();
 54  
 55              // Extract the bits from the scalar field representation.
 56              let candidate_bits_le = candidate.to_bits_le();
 57              assert_eq!(Scalar::<CurrentEnvironment>::size_in_bits(), candidate_bits_le.len());
 58  
 59              // Ensure all integer bits match with the expected result.
 60              let i_bits = usize::try_from(I::BITS).unwrap();
 61              let expected_bits = expected.to_bits_le();
 62              for (expected_bit, candidate_bit) in expected_bits.iter().zip_eq(&candidate_bits_le[0..i_bits]) {
 63                  assert_eq!(expected_bit, candidate_bit);
 64              }
 65  
 66              // Ensure all remaining bits are 0.
 67              for candidate_bit in &candidate_bits_le[i_bits..] {
 68                  assert!(!candidate_bit);
 69              }
 70          }
 71          Ok(())
 72      }
 73  
 74      #[test]
 75      fn test_u8_to_scalar() -> Result<()> {
 76          type I = u8;
 77          check_to_scalar::<I>()
 78      }
 79  
 80      #[test]
 81      fn test_i8_to_scalar() -> Result<()> {
 82          type I = i8;
 83          check_to_scalar::<I>()
 84      }
 85  
 86      #[test]
 87      fn test_u16_to_scalar() -> Result<()> {
 88          type I = u16;
 89          check_to_scalar::<I>()
 90      }
 91  
 92      #[test]
 93      fn test_i16_to_scalar() -> Result<()> {
 94          type I = i16;
 95          check_to_scalar::<I>()
 96      }
 97  
 98      #[test]
 99      fn test_u32_to_scalar() -> Result<()> {
100          type I = u32;
101          check_to_scalar::<I>()
102      }
103  
104      #[test]
105      fn test_i32_to_scalar() -> Result<()> {
106          type I = i32;
107          check_to_scalar::<I>()
108      }
109  
110      #[test]
111      fn test_u64_to_scalar() -> Result<()> {
112          type I = u64;
113          check_to_scalar::<I>()
114      }
115  
116      #[test]
117      fn test_i64_to_scalar() -> Result<()> {
118          type I = i64;
119          check_to_scalar::<I>()
120      }
121  
122      #[test]
123      fn test_u128_to_scalar() -> Result<()> {
124          type I = u128;
125          check_to_scalar::<I>()
126      }
127  
128      #[test]
129      fn test_i128_to_scalar() -> Result<()> {
130          type I = i128;
131          check_to_scalar::<I>()
132      }
133  }