// Ajout le 3/5/2021 par Yves Biton
/*
* MathGraph32 Javascript : Software for animating online dynamic mathematics figures
* https://www.mathgraph32.org/
* @Author Yves Biton (yves.biton@sesamath.net)
* @License: GNU AGPLv3 https://www.gnu.org/licenses/agpl-3.0.html
*/
import mathjs from '../kernel/mathjs'
import CCalculAncetre from './CCalculAncetre'
import CValeur from './CValeur'
import { latexMat, latexMatFrac, SHORT_MAX_VALUE } from '../kernel/kernel'
import NatCal from '../types/NatCal'
const { matrix } = mathjs
export default CMatriceAleat
/**
* Classe représentant une matrice de n lignes et p colonnes à valeurs entières distinctes
* comprises entre les valeurs rendues par min et max
* Les valeurs générées pour la matrice ne pourront être distinctes quue si max-min+1 est
* supérieur ou égal au nombre de termes de la matrice
* @param {CListeObjets} listeProprietaire La liste propriétaire
* @param {CImplementationProto} impProto null ou a construction propriétaire.
* @param {boolean} estElementFinal true si élément final de construction
* @param {string} nomCalcul Le nom donné au calcul.
* @param {number} n Le nombre de lignes de la matrice
* @param {number} p Le nombre de colonnes de la matrice
* @param {CValeur} min La valeur mini des termes de la matrice (dynamique)
* @param {CValeur} max La valeur maxi des termes de la matrice (dynamique)
* @constructor
*/
function CMatriceAleat (listeProprietaire, impProto, estElementFinal, nomCalcul, n, p, min, max) {
if (arguments.length === 0) CCalculAncetre.call(this)
else {
if (arguments.length === 1) CCalculAncetre.call(this, listeProprietaire)
else {
CCalculAncetre.call(this, listeProprietaire, impProto, estElementFinal, nomCalcul)
this.n = n // Le nombre de lignes
this.p = p // Le nombre de colonnes
this.min = min // Valeur mini entière pour les termes de la matrice
this.max = max // Valeur maxi entière pour les termes de la matrice
}
}
}
CMatriceAleat.prototype = new CCalculAncetre()
CMatriceAleat.prototype.constructor = CMatriceAleat
CMatriceAleat.prototype.superClass = 'CCalculAncetre'
CMatriceAleat.prototype.className = 'CMatriceAleat'
// Version 6.7.2 : On passe à la version 3. Les valeur prises par la matrices ne sont plus sauvegardées
// comme des int sur 4 octets mais des number sur 6 octets
CMatriceAleat.prototype.numeroVersion = function () {
return 3
}
CMatriceAleat.prototype.getClone = function (listeSource, listeCible) {
const ind1 = listeSource.indexOf(this.impProto)
const minClone = this.min.getClone(listeSource, listeCible)
const maxClone = this.max.getClone(listeSource, listeCible)
const mataleat =
new CMatriceAleat(listeCible, listeCible.get(ind1, 'CImplementationProto'),
this.estElementFinal, this.nomCalcul, this.n, this.p, minClone, maxClone)
// Version 7.4 : Les valeurs prises par la matrice sont clonées à partir des valeurs prises par
// la matrice this
if (this.mat) { // Pour les précdentes versions
const mat = []
for (let i = 0; i < this.n; i++) {
const lig = []
for (let j = 0; j < this.p; j++) {
lig.push(this.mat.get([i, j]))
}
mat.push(lig)
}
mataleat.mat = matrix(mat)
}
return mataleat
}
CMatriceAleat.prototype.getNatureCalcul = function () {
return NatCal.NMatriceAleat
}
CMatriceAleat.prototype.positionne = function (infoRandom) {
this.min.positionne(infoRandom)
this.max.positionne(infoRandom)
let existe = this.min.existe && this.max.existe
let valmin, valmax
if (existe) {
valmin = this.min.rendValeur()
valmax = this.max.rendValeur()
// Version 7.6.3 (numéro de version 3) : Les valeurs prises doivent être entre -SHORT_MAX_VALUE et SHORT_MAX_VALUE
existe = valmin === Math.round(valmin) && valmax === Math.round(valmax) && (valmin < valmax) &&
(valmax - valmin <= 1000) && (valmin >= -SHORT_MAX_VALUE) && (valmax <= SHORT_MAX_VALUE)
}
this.existe = existe
if (this.existe) {
// Si on ne demande pas un recalcul aléatoire et que la matrice a déjà été calculée on ne la remet pas à jour
if (!infoRandom && this.mat) return
let tab = [] // Tableau qui va contenir tous les nombres entiers de min à max
const tabInit = []
for (let i = valmin; i <= valmax; i++) {
tab.push(i)
tabInit.push(i)
}
const mat = []
for (let i = 0; i < this.n; i++) {
const lig = []
mat.push(lig)
for (let j = 0; j < this.p; j++) {
// On retire une élément au hasard de tab
const k = Math.floor(Math.random() * tab.length)
const val = tab[k]
tab.splice(k, 1)
lig.push(val)
if (tab.length === 0) tab = tabInit.slice(0)
}
}
this.mat = matrix(mat) // Matrice contenant les valeurs aléatoires
}
}
CMatriceAleat.prototype.initialisePourDependance = function () {
CCalculAncetre.prototype.initialisePourDependance.call(this)
this.min.initialisePourDependance()
this.max.initialisePourDependance()
}
CMatriceAleat.prototype.depDe = function (p) {
if (this.elementTestePourDependDe === p) return this.dependDeElementTeste
return this.memDep(CCalculAncetre.prototype.depDe.call(this, p) || this.min.depDe(p) || this.max.depDe(p))
}
CMatriceAleat.prototype.dependDePourBoucle = function (p) {
return (p === this) || this.min.dependDePourBoucle(p) || this.max.dependDePourBoucle(p)
}
CMatriceAleat.prototype.read = function (inps, list) {
CCalculAncetre.prototype.read.call(this, inps, list)
this.n = inps.readInt()
this.p = inps.readInt()
this.min = new CValeur()
this.min.read(inps, list)
this.max = new CValeur()
this.max.read(inps, list)
// A partir de la version 7.4, on a sauvegardé des valeurs de la matrice
// au départ (n° de version 2) sous forme d'un entier sur 4 actets non signés
// puis (version 3) sous la même forme mais on retranche SHORT_MAX_VALUE = 2^16 - 1
// ainsi la valeur paut aller de - SHORT_MAX_VALUE à +SHORT_MAX_VALUE
const nver = this.nVersion
if (nver >= 2) {
const mat = []
for (let i = 0; i < this.n; i++) {
const lig = []
for (let j = 0; j < this.p; j++) {
const ent = inps.readInt()
lig.push(nver === 2 ? ent : ent - SHORT_MAX_VALUE)
}
mat.push(lig)
}
this.mat = matrix(mat)
}
}
CMatriceAleat.prototype.write = function (oups, list) {
CCalculAncetre.prototype.write.call(this, oups, list)
oups.writeInt(this.n)
oups.writeInt(this.p)
this.min.write(oups, list)
this.max.write(oups, list)
// A partir de la version 7.4, on sauvegarde des valeurs de la matrice (nVersion passé à 2)
for (let i = 0; i < this.n; i++) {
for (let j = 0; j < this.p; j++) {
// Version 6.7.3 : On enregistre la valeur à laquelle on additionne SHORT_MAX_VALUE = 2^16 - 1
oups.writeInt(this.mat.get([i, j]) + SHORT_MAX_VALUE)
}
}
}
/**
* Pour l'interprétation syntaxique, les matrices sont considérées comme des fonctions à deu variables
* @returns {number}
*/
CMatriceAleat.prototype.nombreVariables = function () {
return 2
}
/**
* Fonction utilisée dans CalcR. CMatrice, CMatriceAleat sont les seuls objets
* descendant de CValDyn renvoyant true pour cette fonction (matrices ne résultant pas d'un calcul)
* @returns {boolean}
*/
CMatriceAleat.prototype.estMatriceBase = function () {
return true
}
/**
* Fonction utilisée dans CalcR. CMatrice, CMatriceAleat, CMatriceParForm et CCalcMat CCalcMat sont les seuls objets
* descendant de CValDyn renvoyant true pour cette fonction
* @returns {boolean}
*/
CMatriceAleat.prototype.estMatrice = function () {
return true
}
/**
* Fonction renvoyant la représentation LaTeX du résultat de la matrice avec n décimales
* @param {number} nbdec Le nombre de décimales
* @returns {string}
*/
CMatriceAleat.prototype.latexMat = function (nbdec) {
return latexMat(this.mat, nbdec)
}
/**
* Fonction renvoyant la représentation LaTeX du résultat de la matrice avec appriximation
* des valeurs par des fractions rationnelles à 10^(-12) près
* @returns {string}
*/
CMatriceAleat.prototype.latexMatFrac = function () {
return latexMatFrac(this.mat)
}