spl_math/
instruction.rs

1//! Program instructions, used for end-to-end testing and instruction counts
2
3use {
4    crate::id,
5    borsh::{BorshDeserialize, BorshSerialize},
6    solana_program::instruction::Instruction,
7};
8
9/// Instructions supported by the math program, used for testing instruction
10/// counts
11#[derive(Clone, Debug, BorshSerialize, BorshDeserialize, PartialEq)]
12pub enum MathInstruction {
13    /// Calculate the square root of the given u64 with decimals
14    ///
15    /// No accounts required for this instruction
16    PreciseSquareRoot {
17        /// Number underneath the square root sign, whose square root will be
18        /// calculated
19        radicand: u64,
20    },
21    /// Calculate the integer square root of the given u64
22    ///
23    /// No accounts required for this instruction
24    SquareRootU64 {
25        /// Number underneath the square root sign, whose square root will be
26        /// calculated
27        radicand: u64,
28    },
29    /// Calculate the integer square root of the given u128
30    ///
31    /// No accounts required for this instruction
32    SquareRootU128 {
33        /// Number underneath the square root sign, whose square root will be
34        /// calculated
35        radicand: u128,
36    },
37    /// Multiply two u64 values
38    ///
39    /// No accounts required for this instruction
40    U64Multiply {
41        /// The multiplicand
42        multiplicand: u64,
43        /// The multipier
44        multiplier: u64,
45    },
46    /// Divide two u64 values
47    ///
48    /// No accounts required for this instruction
49    U64Divide {
50        /// The dividend
51        dividend: u64,
52        /// The divisor
53        divisor: u64,
54    },
55    /// Multiply two float values
56    ///
57    /// No accounts required for this instruction
58    F32Multiply {
59        /// The multiplicand
60        multiplicand: f32,
61        /// The multipier
62        multiplier: f32,
63    },
64    /// Divide two float values
65    ///
66    /// No accounts required for this instruction
67    F32Divide {
68        /// The dividend
69        dividend: f32,
70        /// The divisor
71        divisor: f32,
72    },
73
74    /// Exponentiate a float base by a power
75    ///
76    /// No accounts required for this instruction
77    F32Exponentiate {
78        /// The base
79        base: f32,
80        /// The exponent
81        exponent: f32,
82    },
83
84    /// Natural Log of a float
85    ///
86    /// No accounts required for this instruction
87    F32NaturalLog {
88        /// The argument
89        argument: f32,
90    },
91
92    /// The Normal CDF of a float
93    ///
94    /// No accounts required for this instruction
95    F32NormalCDF {
96        /// The argument
97        argument: f32,
98    },
99
100    /// Pow two float values
101    ///
102    /// No accounts required for this instruction
103    F64Pow {
104        /// The base
105        base: f64,
106        /// The exponent
107        exponent: f64,
108    },
109
110    /// Multiply two u128 values
111    ///
112    /// No accounts required for this instruction
113    U128Multiply {
114        /// The multiplicand
115        multiplicand: u128,
116        /// The multipier
117        multiplier: u128,
118    },
119    /// Divide two u128 values
120    ///
121    /// No accounts required for this instruction
122    U128Divide {
123        /// The dividend
124        dividend: u128,
125        /// The divisor
126        divisor: u128,
127    },
128    /// Multiply two f64 values
129    ///
130    /// No accounts required for this instruction
131    F64Multiply {
132        /// The multiplicand
133        multiplicand: f64,
134        /// The multipier
135        multiplier: f64,
136    },
137    /// Divide two f64 values
138    ///
139    /// No accounts required for this instruction
140    F64Divide {
141        /// The dividend
142        dividend: f64,
143        /// The divisor
144        divisor: f64,
145    },
146
147    /// Don't do anything for comparison
148    ///
149    /// No accounts required for this instruction
150    Noop,
151}
152
153/// Create PreciseSquareRoot instruction
154pub fn precise_sqrt(radicand: u64) -> Instruction {
155    Instruction {
156        program_id: id(),
157        accounts: vec![],
158        data: borsh::to_vec(&MathInstruction::PreciseSquareRoot { radicand }).unwrap(),
159    }
160}
161
162/// Create U64 SquareRoot instruction
163pub fn sqrt_u64(radicand: u64) -> Instruction {
164    Instruction {
165        program_id: id(),
166        accounts: vec![],
167        data: borsh::to_vec(&MathInstruction::SquareRootU64 { radicand }).unwrap(),
168    }
169}
170
171/// Create U128 SquareRoot instruction
172pub fn sqrt_u128(radicand: u128) -> Instruction {
173    Instruction {
174        program_id: id(),
175        accounts: vec![],
176        data: borsh::to_vec(&MathInstruction::SquareRootU128 { radicand }).unwrap(),
177    }
178}
179
180/// Create U64 Multiplication instruction
181pub fn u64_multiply(multiplicand: u64, multiplier: u64) -> Instruction {
182    Instruction {
183        program_id: id(),
184        accounts: vec![],
185        data: borsh::to_vec(&MathInstruction::U64Multiply {
186            multiplicand,
187            multiplier,
188        })
189        .unwrap(),
190    }
191}
192
193/// Create U64 Division instruction
194pub fn u64_divide(dividend: u64, divisor: u64) -> Instruction {
195    Instruction {
196        program_id: id(),
197        accounts: vec![],
198        data: borsh::to_vec(&MathInstruction::U64Divide { dividend, divisor }).unwrap(),
199    }
200}
201
202/// Create F32 Multiplication instruction
203pub fn f32_multiply(multiplicand: f32, multiplier: f32) -> Instruction {
204    Instruction {
205        program_id: id(),
206        accounts: vec![],
207        data: borsh::to_vec(&MathInstruction::F32Multiply {
208            multiplicand,
209            multiplier,
210        })
211        .unwrap(),
212    }
213}
214
215/// Create F32 Division instruction
216pub fn f32_divide(dividend: f32, divisor: f32) -> Instruction {
217    Instruction {
218        program_id: id(),
219        accounts: vec![],
220        data: borsh::to_vec(&MathInstruction::F32Divide { dividend, divisor }).unwrap(),
221    }
222}
223
224/// Create F32 Exponentiate instruction
225pub fn f32_exponentiate(base: f32, exponent: f32) -> Instruction {
226    Instruction {
227        program_id: id(),
228        accounts: vec![],
229        data: borsh::to_vec(&MathInstruction::F32Exponentiate { base, exponent }).unwrap(),
230    }
231}
232
233/// Create F32 Natural Log instruction
234pub fn f32_natural_log(argument: f32) -> Instruction {
235    Instruction {
236        program_id: id(),
237        accounts: vec![],
238        data: borsh::to_vec(&MathInstruction::F32NaturalLog { argument }).unwrap(),
239    }
240}
241
242/// Create F32 Normal CDF instruction
243pub fn f32_normal_cdf(argument: f32) -> Instruction {
244    Instruction {
245        program_id: id(),
246        accounts: vec![],
247        data: borsh::to_vec(&MathInstruction::F32NormalCDF { argument }).unwrap(),
248    }
249}
250
251/// Create F64Pow instruction
252pub fn f64_pow(base: f64, exponent: f64) -> Instruction {
253    Instruction {
254        program_id: id(),
255        accounts: vec![],
256        data: borsh::to_vec(&MathInstruction::F64Pow { base, exponent }).unwrap(),
257    }
258}
259
260/// Create U128 Multiplication instruction
261pub fn u128_multiply(multiplicand: u128, multiplier: u128) -> Instruction {
262    Instruction {
263        program_id: id(),
264        accounts: vec![],
265        data: borsh::to_vec(&MathInstruction::U128Multiply {
266            multiplicand,
267            multiplier,
268        })
269        .unwrap(),
270    }
271}
272
273/// Create U128 Division instruction
274pub fn u128_divide(dividend: u128, divisor: u128) -> Instruction {
275    Instruction {
276        program_id: id(),
277        accounts: vec![],
278        data: borsh::to_vec(&MathInstruction::U128Divide { dividend, divisor }).unwrap(),
279    }
280}
281
282/// Create F64 Multiplication instruction
283pub fn f64_multiply(multiplicand: f64, multiplier: f64) -> Instruction {
284    Instruction {
285        program_id: id(),
286        accounts: vec![],
287        data: borsh::to_vec(&MathInstruction::F64Multiply {
288            multiplicand,
289            multiplier,
290        })
291        .unwrap(),
292    }
293}
294
295/// Create F64 Division instruction
296pub fn f64_divide(dividend: f64, divisor: f64) -> Instruction {
297    Instruction {
298        program_id: id(),
299        accounts: vec![],
300        data: borsh::to_vec(&MathInstruction::F64Divide { dividend, divisor }).unwrap(),
301    }
302}
303
304/// Create Noop instruction
305pub fn noop() -> Instruction {
306    Instruction {
307        program_id: id(),
308        accounts: vec![],
309        data: borsh::to_vec(&MathInstruction::Noop).unwrap(),
310    }
311}
312
313#[cfg(test)]
314mod tests {
315    use super::*;
316
317    #[test]
318    fn test_precise_sqrt() {
319        let instruction = precise_sqrt(u64::MAX);
320        assert_eq!(0, instruction.accounts.len());
321        assert_eq!(
322            instruction.data,
323            borsh::to_vec(&MathInstruction::PreciseSquareRoot { radicand: u64::MAX }).unwrap()
324        );
325        assert_eq!(instruction.program_id, crate::id());
326    }
327
328    #[test]
329    fn test_sqrt_u64() {
330        let instruction = sqrt_u64(u64::MAX);
331        assert_eq!(0, instruction.accounts.len());
332        assert_eq!(
333            instruction.data,
334            borsh::to_vec(&MathInstruction::SquareRootU64 { radicand: u64::MAX }).unwrap()
335        );
336        assert_eq!(instruction.program_id, crate::id());
337    }
338
339    #[test]
340    fn test_sqrt_u128() {
341        let instruction = sqrt_u128(u128::MAX);
342        assert_eq!(0, instruction.accounts.len());
343        assert_eq!(
344            instruction.data,
345            borsh::to_vec(&MathInstruction::SquareRootU128 {
346                radicand: u128::MAX
347            })
348            .unwrap()
349        );
350        assert_eq!(instruction.program_id, crate::id());
351    }
352
353    #[test]
354    fn test_u64_multiply() {
355        let instruction = u64_multiply(u64::MAX, u64::MAX);
356        assert_eq!(0, instruction.accounts.len());
357        assert_eq!(
358            instruction.data,
359            borsh::to_vec(&MathInstruction::U64Multiply {
360                multiplicand: u64::MAX,
361                multiplier: u64::MAX
362            })
363            .unwrap()
364        );
365        assert_eq!(instruction.program_id, crate::id());
366    }
367
368    #[test]
369    fn test_u64_divide() {
370        let instruction = u64_divide(u64::MAX, u64::MAX);
371        assert_eq!(0, instruction.accounts.len());
372        assert_eq!(
373            instruction.data,
374            borsh::to_vec(&MathInstruction::U64Divide {
375                dividend: u64::MAX,
376                divisor: u64::MAX
377            })
378            .unwrap()
379        );
380        assert_eq!(instruction.program_id, crate::id());
381    }
382
383    #[test]
384    fn test_f32_multiply() {
385        let instruction = f32_multiply(f32::MAX, f32::MAX);
386        assert_eq!(0, instruction.accounts.len());
387        assert_eq!(
388            instruction.data,
389            borsh::to_vec(&MathInstruction::F32Multiply {
390                multiplicand: f32::MAX,
391                multiplier: f32::MAX
392            })
393            .unwrap()
394        );
395        assert_eq!(instruction.program_id, crate::id());
396    }
397
398    #[test]
399    fn test_f32_divide() {
400        let instruction = f32_divide(f32::MAX, f32::MAX);
401        assert_eq!(0, instruction.accounts.len());
402        assert_eq!(
403            instruction.data,
404            borsh::to_vec(&MathInstruction::F32Divide {
405                dividend: f32::MAX,
406                divisor: f32::MAX
407            })
408            .unwrap()
409        );
410        assert_eq!(instruction.program_id, crate::id());
411    }
412
413    #[test]
414    fn test_f32_exponentiate() {
415        let instruction = f32_exponentiate(f32::MAX, f32::MAX);
416        assert_eq!(0, instruction.accounts.len());
417        assert_eq!(
418            instruction.data,
419            borsh::to_vec(&MathInstruction::F32Exponentiate {
420                base: f32::MAX,
421                exponent: f32::MAX
422            })
423            .unwrap()
424        );
425        assert_eq!(instruction.program_id, crate::id())
426    }
427
428    #[test]
429    fn test_f32_natural_log() {
430        let instruction = f32_natural_log(f32::MAX);
431        assert_eq!(0, instruction.accounts.len());
432        assert_eq!(
433            instruction.data,
434            borsh::to_vec(&MathInstruction::F32NaturalLog { argument: f32::MAX }).unwrap()
435        );
436        assert_eq!(instruction.program_id, crate::id())
437    }
438
439    #[test]
440    fn test_f32_normal_cdf() {
441        let instruction = f32_normal_cdf(f32::MAX);
442        assert_eq!(0, instruction.accounts.len());
443        assert_eq!(
444            instruction.data,
445            borsh::to_vec(&MathInstruction::F32NormalCDF { argument: f32::MAX }).unwrap()
446        );
447        assert_eq!(instruction.program_id, crate::id())
448    }
449
450    #[test]
451    fn test_noop() {
452        let instruction = noop();
453        assert_eq!(0, instruction.accounts.len());
454        assert_eq!(
455            instruction.data,
456            borsh::to_vec(&MathInstruction::Noop).unwrap()
457        );
458        assert_eq!(instruction.program_id, crate::id());
459    }
460}